From 28fec77c1a96e1cc9cea0a5d9b4f04defa4ffe2d Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 26 Apr 2017 15:32:35 +0800 Subject: [PATCH 01/62] 2017-04-26 update 1 Add extend interface for Machine and Utility. --- .../Modbus.Net.Core/Modbus.Net.Core.csproj | 8 +- .../Modbus.Net.Modbus.csproj | 6 +- Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 17 ++- .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 6 +- .../Modbus.Net.Siemens.csproj | 6 +- .../Modbus.Net.Siemens/SiemensUtility.cs | 20 +--- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 8 +- Modbus.Net/src/Base.Common/BaseMachine.cs | 88 +++++++++++++- Modbus.Net/src/Base.Common/BaseUtility.cs | 17 +-- Modbus.Net/src/Base.Common/IMachineMethod.cs | 47 ++++++++ Modbus.Net/src/Base.Common/IUtilityMethod.cs | 113 ++++++++++++++++++ Modbus.Net/src/Base.Common/TaskManager.cs | 11 -- .../MachineUtilityMethodTest.cs | 62 ++++++++++ .../Modbus.Net.Tests/Modbus.Net.Tests.csproj | 1 + 14 files changed, 352 insertions(+), 58 deletions(-) create mode 100644 Modbus.Net/src/Base.Common/IMachineMethod.cs create mode 100644 Modbus.Net/src/Base.Common/IUtilityMethod.cs create mode 100644 Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs 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 @@ + From 80991bafbdbae515424d354ed0aa253514361a4f Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 26 Apr 2017 16:31:54 +0800 Subject: [PATCH 02/62] 2017-04-26 update 2 TaskManager data function call change. --- Modbus.Net/src/Base.Common/BaseMachine.cs | 24 +++++++++++++++-------- Modbus.Net/src/Base.Common/TaskManager.cs | 6 ++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index f3c5ec2..2a3a208 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -868,18 +868,26 @@ namespace Modbus.Net bool KeepConnect { get; set; } /// - /// 读取数据 + /// 调用Machine中的方法 /// - /// 从设备读取的数据 - Task> GetDatasAsync(MachineGetDataType getDataType); + /// Machine实现的接口名称 + /// 返回值的类型 + /// 方法的名称 + /// 方法的参数 + /// + TReturnType InvokeMachineMethod(string methodName, + params object[] parameters) where TMachineMethod : IMachineMethod; /// - /// 写入数据 + /// 调用Utility中的方法 /// - /// 写入类型 - /// 需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述 - /// 是否写入成功 - Task SetDatasAsync(MachineSetDataType setDataType, Dictionary values); + /// Utility实现的接口名称 + /// 返回值的类型 + /// 方法的名称 + /// 方法的参数 + /// + TReturnType InvokeUtilityMethod(string methodName, + params object[] parameters) where TUtilityMethod : IUtilityMethod; /// /// 连接设备 diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 387ff71..cd73294 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -725,7 +725,7 @@ namespace Modbus.Net machine = _machines.FirstOrDefault(p => p.ConnectionToken == connectionToken); } if (machine == null) return false; - return await machine.SetDatasAsync(SetDataType, values); + return await machine.InvokeMachineMethod>("SetDatasAsync", SetDataType, values); } /// @@ -798,7 +798,9 @@ namespace Modbus.Net //超时后取消任务 cts.CancelAfter(TimeSpan.FromSeconds(_getCycle)); //读取数据 - var ans = await machine.GetDatasAsync(GetDataType).WithCancellation(cts.Token); + var ans = + await machine.InvokeMachineMethod>>("GetDatasAsync", + GetDataType).WithCancellation(cts.Token); if (!machine.IsConnected) { MoveMachineToUnlinked(machine.Id); From 8380c955707d3d349bc54a37bef9bfb63da4177f Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 28 Apr 2017 09:32:02 +0800 Subject: [PATCH 03/62] Test Fix --- ...lityMethodTest.cs => MachineMethodTest.cs} | 29 ++++++++++++------- .../Modbus.Net.Tests/Modbus.Net.Tests.csproj | 2 +- 2 files changed, 20 insertions(+), 11 deletions(-) rename Tests/Modbus.Net.Tests/{MachineUtilityMethodTest.cs => MachineMethodTest.cs} (59%) diff --git a/Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs similarity index 59% rename from Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs rename to Tests/Modbus.Net.Tests/MachineMethodTest.cs index ebfadb2..0434c43 100644 --- a/Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -9,7 +9,7 @@ using Modbus.Net.Modbus; namespace Modbus.Net.Tests { [TestClass] - public class MachineUtilityMethodTest + public class MachineMethodTest { [TestMethod] public void GetUtility() @@ -25,16 +25,16 @@ namespace Modbus.Net.Tests 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); + var success = await baseMachine.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); + Assert.AreEqual(success, true); + var time = await baseMachine.InvokeUtilityMethod>("GetTimeAsync"); + Assert.AreEqual((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> + BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.10", new List> { new AddressUnit { @@ -46,7 +46,7 @@ namespace Modbus.Net.Tests DataType = typeof(bool) } }, true, 2, 0); - var success = baseMachine.InvokeMachineMethod>("SetDatasAsync", + var success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", MachineSetDataType.Address, new Dictionary { @@ -54,9 +54,18 @@ namespace Modbus.Net.Tests "0X 1.0", 1 } }); - Assert.AreEqual(await success, true); - var datas = baseMachine.InvokeMachineMethod>>("GetDatasAsync", MachineGetDataType.Address); - Assert.AreEqual((await datas)["0X 1.0"], 1); + Assert.AreEqual(success, true); + var datas = await baseMachine.InvokeMachineMethod>>("GetDatasAsync", MachineGetDataType.Address); + Assert.AreEqual(datas["0X 1.0"].PlcValue, 1); + success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", + MachineSetDataType.Address, + new Dictionary + { + { + "0X 1.0", 0 + } + }); + Assert.AreEqual(success, true); } } } diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index 022c561..aaf4bb9 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -57,7 +57,7 @@ - + From 069b0a56e1e7882ecca716ad2487593e0504ad35 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 28 Apr 2017 17:17:59 +0800 Subject: [PATCH 04/62] 2017-04-28 update 1 Add combiner max limit. --- Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs | 8 +- .../Modbus.Net.Siemens/SiemensMachine.cs | 8 +- Modbus.Net/src/Base.Common/AddressCombiner.cs | 74 ++++++++++++++---- Tests/Modbus.Net.Tests/BaseTest.cs | 78 ++++++++++++++++++- 4 files changed, 143 insertions(+), 25 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs index 07ed8b9..450a12d 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs @@ -16,8 +16,8 @@ namespace Modbus.Net.Modbus { BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian); AddressFormater = new AddressFormaterModbus(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public ModbusMachine(ModbusType connectionType, string connectionString, @@ -40,8 +40,8 @@ namespace Modbus.Net.Modbus { BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian); AddressFormater = new AddressFormaterModbus(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public ModbusMachine(ModbusType connectionType, string connectionString, diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs index 5c0e607..f91495c 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs @@ -15,8 +15,8 @@ namespace Modbus.Net.Siemens { BaseUtility = new SiemensUtility(connectionType, connectionString, model, slaveAddress, masterAddress); AddressFormater = new AddressFormaterSiemens(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, @@ -37,8 +37,8 @@ namespace Modbus.Net.Siemens { BaseUtility = new SiemensUtility(connectionType, connectionString, model, slaveAddress, masterAddress); AddressFormater = new AddressFormaterSiemens(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, diff --git a/Modbus.Net/src/Base.Common/AddressCombiner.cs b/Modbus.Net/src/Base.Common/AddressCombiner.cs index 3c7ef51..f60226a 100644 --- a/Modbus.Net/src/Base.Common/AddressCombiner.cs +++ b/Modbus.Net/src/Base.Common/AddressCombiner.cs @@ -29,7 +29,7 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombinerContinus { - public AddressCombinerContinus(AddressTranslator addressTranslator) : base(addressTranslator) + public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) : base(addressTranslator, maxLength) { } } @@ -39,9 +39,12 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombiner where TKey : IEquatable { - public AddressCombinerContinus(AddressTranslator addressTranslator) + protected int MaxLength { get; set; } + + public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) { AddressTranslator = addressTranslator; + MaxLength = maxLength; } protected AddressTranslator AddressTranslator { get; set; } @@ -158,7 +161,48 @@ namespace Modbus.Net OriginalAddresses = originalAddresses.ToList() }); } - return ans; + List> newAns = new List>(); + foreach (var communicationUnit in ans) + { + double oldByteCount = communicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]; + while (oldByteCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName] > + MaxLength) + { + var newOriginalAddresses = new List>(); + var oldOriginalAddresses = communicationUnit.OriginalAddresses.ToList(); + var newByteCount = 0.0; + do + { + var currentAddressUnit = oldOriginalAddresses.First(); + newByteCount += BigEndianValueHelper.Instance.ByteLength[currentAddressUnit.DataType.FullName]; + if (newByteCount > MaxLength) break; + oldByteCount -= BigEndianValueHelper.Instance.ByteLength[currentAddressUnit.DataType.FullName]; + newOriginalAddresses.Add(currentAddressUnit); + oldOriginalAddresses.RemoveAt(0); + + } while (newByteCount < MaxLength); + var newCommunicationUnit = new CommunicationUnit + { + Area = communicationUnit.Area, + Address = communicationUnit.Address, + SubAddress = communicationUnit.SubAddress, + DataType = communicationUnit.DataType, + GetCount = + (int) + Math.Ceiling(newByteCount / + BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]), + OriginalAddresses = newOriginalAddresses, + }; + + newAns.Add(newCommunicationUnit); + } + communicationUnit.GetCount = + (int) + Math.Ceiling(oldByteCount / + BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]); + newAns.Add(communicationUnit); + } + return newAns; } } @@ -205,8 +249,8 @@ namespace Modbus.Net /// public class AddressCombinerNumericJump : AddressCombinerNumericJump { - public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator) - : base(jumpByteCount, addressTranslator) + public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator) + : base(jumpByteCount, maxLength, addressTranslator) { } } @@ -216,8 +260,8 @@ namespace Modbus.Net /// public class AddressCombinerNumericJump : AddressCombinerContinus where TKey : IEquatable { - public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator) - : base(addressTranslator) + public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator) + : base(addressTranslator, maxLength) { JumpNumber = jumpByteCount; } @@ -260,12 +304,14 @@ namespace Modbus.Net var jumpNumberInner = JumpNumber; foreach (var orderedGap in orderedGaps) { - jumpNumberInner -= orderedGap.GapNumber; - if (jumpNumberInner < 0) break; + if (orderedGap.GapNumber <= 0) continue; var nowAddress = orderedGap.EndUnit; var index = continusAddresses.IndexOf(nowAddress); index--; var preAddress = continusAddresses[index]; + if (nowAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName] + preAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName] + orderedGap.GapNumber > MaxLength) continue; + jumpNumberInner -= orderedGap.GapNumber; + if (jumpNumberInner < 0) break; continusAddresses.RemoveAt(index); continusAddresses.RemoveAt(index); //合并两个已有的地址段,变为一个新的地址段 @@ -293,8 +339,8 @@ namespace Modbus.Net /// public class AddressCombinerPercentageJump : AddressCombinerPercentageJump { - public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator) - : base(percentage, addressTranslator) + public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator) + : base(percentage, maxLength, addressTranslator) { } } @@ -304,8 +350,8 @@ namespace Modbus.Net /// public class AddressCombinerPercentageJump : AddressCombinerContinus where TKey : IEquatable { - public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator) - : base(addressTranslator) + public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator) + : base(addressTranslator, maxLength) { if (percentage < 0) percentage = 0; Percentage = percentage; @@ -318,7 +364,7 @@ namespace Modbus.Net var addressUnits = addresses as IList> ?? addresses.ToList(); var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]); return - new AddressCombinerNumericJump((int) (count*Percentage/100.0), AddressTranslator).Combine( + new AddressCombinerNumericJump((int) (count*Percentage/100.0), MaxLength, AddressTranslator).Combine( addressUnits); } } diff --git a/Tests/Modbus.Net.Tests/BaseTest.cs b/Tests/Modbus.Net.Tests/BaseTest.cs index 45f9b1a..c6b1249 100644 --- a/Tests/Modbus.Net.Tests/BaseTest.cs +++ b/Tests/Modbus.Net.Tests/BaseTest.cs @@ -151,7 +151,7 @@ namespace Modbus.Net.Tests [TestMethod] public void AddressCombinerContinusTest() { - var addressCombiner = new AddressCombinerContinus(new AddressTranslatorModbus()); + var addressCombiner = new AddressCombinerContinus(new AddressTranslatorModbus(), 100000); var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); Assert.AreEqual(combinedAddresses[0].Area, "3X"); Assert.AreEqual(combinedAddresses[0].Address, 1); @@ -176,6 +176,37 @@ namespace Modbus.Net.Tests Assert.AreEqual(combinedAddresses[6].GetCount, 2); } + [TestMethod] + public void AddressCombinerContinusLimitTest() + { + var addressCombiner = new AddressCombinerContinus(new AddressTranslatorModbus(), 4); + var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); + Assert.AreEqual(combinedAddresses[0].Area, "3X"); + Assert.AreEqual(combinedAddresses[0].Address, 1); + Assert.AreEqual(combinedAddresses[0].GetCount, 1); + Assert.AreEqual(combinedAddresses[1].Area, "3X"); + Assert.AreEqual(combinedAddresses[1].Address, 2); + Assert.AreEqual(combinedAddresses[1].GetCount, 4); + Assert.AreEqual(combinedAddresses[2].Area, "3X"); + Assert.AreEqual(combinedAddresses[2].Address, 2); + Assert.AreEqual(combinedAddresses[2].GetCount, 2); + Assert.AreEqual(combinedAddresses[3].Area, "3X"); + Assert.AreEqual(combinedAddresses[3].Address, 6); + Assert.AreEqual(combinedAddresses[3].GetCount, 2); + Assert.AreEqual(combinedAddresses[4].Area, "3X"); + Assert.AreEqual(combinedAddresses[4].Address, 9); + Assert.AreEqual(combinedAddresses[4].GetCount, 4); + Assert.AreEqual(combinedAddresses[5].Area, "3X"); + Assert.AreEqual(combinedAddresses[5].Address, 100); + Assert.AreEqual(combinedAddresses[5].GetCount, 2); + Assert.AreEqual(combinedAddresses[6].Area, "4X"); + Assert.AreEqual(combinedAddresses[6].Address, 1); + Assert.AreEqual(combinedAddresses[6].GetCount, 4); + Assert.AreEqual(combinedAddresses[7].Area, "4X"); + Assert.AreEqual(combinedAddresses[7].Address, 4); + Assert.AreEqual(combinedAddresses[7].GetCount, 2); + } + [TestMethod] public void AddressCombinerSingleTest() { @@ -203,7 +234,7 @@ namespace Modbus.Net.Tests [TestMethod] public void AddressCombinerNumericJumpTest() { - var addressCombiner = new AddressCombinerNumericJump(10, new AddressTranslatorModbus()); + var addressCombiner = new AddressCombinerNumericJump(10, 100000, new AddressTranslatorModbus()); var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); Assert.AreEqual(combinedAddresses[0].Area, "3X"); Assert.AreEqual(combinedAddresses[0].Address, 1); @@ -216,10 +247,29 @@ namespace Modbus.Net.Tests Assert.AreEqual(combinedAddresses[2].GetCount, 8); } + [TestMethod] + public void AddressCombinerNumericJumpLimitTest() + { + var addressCombiner = new AddressCombinerNumericJump(10, 10, new AddressTranslatorModbus()); + var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); + Assert.AreEqual(combinedAddresses[0].Area, "3X"); + Assert.AreEqual(combinedAddresses[0].Address, 1); + Assert.AreEqual(combinedAddresses[0].GetCount, 8); + Assert.AreEqual(combinedAddresses[1].Area, "3X"); + Assert.AreEqual(combinedAddresses[1].Address, 6); + Assert.AreEqual(combinedAddresses[1].GetCount, 10); + Assert.AreEqual(combinedAddresses[2].Area, "3X"); + Assert.AreEqual(combinedAddresses[2].Address, 100); + Assert.AreEqual(combinedAddresses[2].GetCount, 2); + Assert.AreEqual(combinedAddresses[3].Area, "4X"); + Assert.AreEqual(combinedAddresses[3].Address, 1); + Assert.AreEqual(combinedAddresses[3].GetCount, 8); + } + [TestMethod] public void AddressCombinerPercentageJumpTest() { - var addressCombiner = new AddressCombinerPercentageJump(30.0, new AddressTranslatorModbus()); + var addressCombiner = new AddressCombinerPercentageJump(30.0, 100000, new AddressTranslatorModbus()); var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); Assert.AreEqual(combinedAddresses[0].Area, "3X"); Assert.AreEqual(combinedAddresses[0].Address, 1); @@ -235,6 +285,28 @@ namespace Modbus.Net.Tests Assert.AreEqual(combinedAddresses[3].GetCount, 8); } + [TestMethod] + public void AddressCombinerPercentageJumpLimitTest() + { + var addressCombiner = new AddressCombinerPercentageJump(30.0, 10, new AddressTranslatorModbus()); + var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); + Assert.AreEqual(combinedAddresses[0].Area, "3X"); + Assert.AreEqual(combinedAddresses[0].Address, 1); + Assert.AreEqual(combinedAddresses[0].GetCount, 8); + Assert.AreEqual(combinedAddresses[1].Area, "3X"); + Assert.AreEqual(combinedAddresses[1].Address, 6); + Assert.AreEqual(combinedAddresses[1].GetCount, 2); + Assert.AreEqual(combinedAddresses[2].Area, "3X"); + Assert.AreEqual(combinedAddresses[2].Address, 9); + Assert.AreEqual(combinedAddresses[2].GetCount, 4); + Assert.AreEqual(combinedAddresses[3].Area, "3X"); + Assert.AreEqual(combinedAddresses[3].Address, 100); + Assert.AreEqual(combinedAddresses[3].GetCount, 2); + Assert.AreEqual(combinedAddresses[4].Area, "4X"); + Assert.AreEqual(combinedAddresses[4].Address, 1); + Assert.AreEqual(combinedAddresses[4].GetCount, 8); + } + [TestMethod] public void TaskManagerGetMachineTest() { From 315f51928fd87336781a21a9e784151993a2f1e5 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 2 May 2017 09:35:57 +0800 Subject: [PATCH 05/62] Emergency Fix: Support .NET Core --- Modbus.Net/src/Base.Common/BaseConnector.cs | 18 +++++++++++++----- Modbus.Net/src/Base.Common/BaseMachine.cs | 6 ++---- Tests/Modbus.Net.Tests/MachineMethodTest.cs | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseConnector.cs b/Modbus.Net/src/Base.Common/BaseConnector.cs index a237210..0d32421 100644 --- a/Modbus.Net/src/Base.Common/BaseConnector.cs +++ b/Modbus.Net/src/Base.Common/BaseConnector.cs @@ -5,7 +5,15 @@ namespace Modbus.Net /// /// 基础的协议连接类 /// - public abstract class BaseConnector + public abstract class BaseConnector : BaseConnector + { + + } + + /// + /// 基础的协议连接类 + /// + public abstract class BaseConnector { /// /// 标识Connector的连接关键字 @@ -40,27 +48,27 @@ namespace Modbus.Net /// /// 需要发送的数据 /// 是否发送成功 - public abstract bool SendMsgWithoutReturn(byte[] message); + public abstract bool SendMsgWithoutReturn(TParamIn message); /// /// 无返回发送数据 /// /// 需要发送的数据 /// 是否发送成功 - public abstract Task SendMsgWithoutReturnAsync(byte[] message); + public abstract Task SendMsgWithoutReturnAsync(TParamIn message); /// /// 带返回发送数据 /// /// 需要发送的数据 /// 是否发送成功 - public abstract byte[] SendMsg(byte[] message); + public abstract TParamOut SendMsg(TParamIn message); /// /// 带返回发送数据 /// /// 需要发送的数据 /// 是否发送成功 - public abstract Task SendMsgAsync(byte[] message); + public abstract Task SendMsgAsync(TParamIn message); } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 2a3a208..b367f3a 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -594,8 +594,7 @@ namespace Modbus.Net if (BaseUtility is TUtilityMethod) { Type t = typeof(TUtilityMethod); - object returnValue = t.GetMethod(methodName, - BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public) + object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) .Invoke(BaseUtility, parameters); return (TReturnType) returnValue; } @@ -616,8 +615,7 @@ namespace Modbus.Net if (this is TMachineMethod) { Type t = typeof(TMachineMethod); - object returnValue = t.GetMethod(methodName, - BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public) + object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) .Invoke(this, parameters); return (TReturnType) returnValue; } diff --git a/Tests/Modbus.Net.Tests/MachineMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs index 0434c43..be08009 100644 --- a/Tests/Modbus.Net.Tests/MachineMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -16,7 +16,7 @@ namespace Modbus.Net.Tests { 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); + var methods = utility.GetType().GetRuntimeMethods(); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetTimeAsync") != null, true); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetTimeAsync") != null, true); } From c13b7dccb09dea295459398155826a8bb895e64a Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 3 May 2017 17:08:50 +0800 Subject: [PATCH 06/62] 2017-05-03 update 1 Base Connector Template (Not Test) --- Modbus.Net/Modbus.Net.OPC/ClientExtend.cs | 14 ++ Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 114 ++++++-------- .../Modbus.Net.OPC/OpcDaProtocalLinker.cs | 11 +- Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs | 44 +++--- .../Modbus.Net.OPC/OpcProtocalLinker.cs | 24 +++ .../Modbus.Net.OPC/OpcUaProtocalLinker.cs | 11 +- Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 6 +- Modbus.Net/src/Base.Common/BaseMachine.cs | 45 ++---- Modbus.Net/src/Base.Common/BaseProtocal.cs | 139 ++++++++++-------- Modbus.Net/src/Base.Common/BaseUtility.cs | 121 ++++++++++++++- .../src/Base.Common/IProtocalFormatting.cs | 23 ++- Modbus.Net/src/Base.Common/ProtocalLinker.cs | 99 ++++++++++--- Modbus.Net/src/Base.Common/ProtocalUnit.cs | 16 +- .../TripleAdd/Controllers/HomeController.cs | 4 +- Tests/Modbus.Net.Tests/MachineMethodTest.cs | 4 +- 15 files changed, 437 insertions(+), 238 deletions(-) create mode 100644 Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs diff --git a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs index d60b351..7539f34 100644 --- a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs +++ b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs @@ -45,4 +45,18 @@ namespace Modbus.Net.OPC public Node RootNodeBase => RootNode; } + + public class OpcParamIn + { + public bool IsRead { get; set; } + public string Tag { get; set; } + public char Split { get; set; } + public object SetValue { get; set; } + } + + public class OpcParamOut + { + public bool Success { get; set; } + public byte[] Value { get; set; } + } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index d78d95e..8c4eb6f 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace Modbus.Net.OPC { - public abstract class OpcConnector : BaseConnector + public abstract class OpcConnector : BaseConnector { protected IClientExtend Client; @@ -39,17 +39,17 @@ namespace Modbus.Net.OPC } } - public override bool SendMsgWithoutReturn(byte[] message) + public override bool SendMsgWithoutReturn(OpcParamIn message) { throw new NotImplementedException(); } - public override Task SendMsgWithoutReturnAsync(byte[] message) + public override Task SendMsgWithoutReturnAsync(OpcParamIn message) { throw new NotImplementedException(); } - public override byte[] SendMsg(byte[] message) + public override OpcParamOut SendMsg(OpcParamIn message) { return AsyncHelper.RunSync(() => SendMsgAsync(message)); } @@ -88,82 +88,41 @@ namespace Modbus.Net.OPC return tagSplitList.ToArray(); } - public override async Task SendMsgAsync(byte[] message) + public override async Task SendMsgAsync(OpcParamIn message) { try { - var pos = 0; - var protocal = BigEndianValueHelper.Instance.GetByte(message, ref pos); - if (protocal == 0) + if (message.IsRead) { - var tagBytes = new byte[message.Length - 6]; - Array.Copy(message, 1, tagBytes, 0, tagBytes.Length); - pos += tagBytes.Length; - pos += 4; - var split = Encoding.UTF8.GetString(new[] { message[pos] }); - var tag = Encoding.UTF8.GetString(tagBytes); - var tagSplit = SplitTag(tag, split[0]); + var split = message.Split; + var tag = message.Tag; + var tagSplit = SplitTag(tag, split); var rootDirectory = await Client.ExploreFolderAsync(""); - var answerTag = await SearchTag(tagSplit, split[0], 0, rootDirectory); + var answerTag = await SearchTag(tagSplit, split, 0, rootDirectory); if (answerTag != null) { var result = await Client.ReadAsync(answerTag); - return BigEndianValueHelper.Instance.GetBytes(result, result.GetType()); + return new OpcParamOut + { + Success = true, + Value = BigEndianValueHelper.Instance.GetBytes(result, result.GetType()) + }; } - return Encoding.ASCII.GetBytes("NoData"); + return new OpcParamOut() + { + Success = false, + Value = Encoding.ASCII.GetBytes("NoData") + }; } else { - var index = 0; - for (var i = 1; i < message.Length - 3; i++) - { - if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff && - message[i + 3] == 0x00) - { - index = i; - break; - } - } - - var index2 = 0; - for (var i = index + 4; i < message.Length - 3; i++) - { - if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff && - message[i + 3] == 0x00) - { - index2 = i; - break; - } - } - - var index3 = 0; - for (var i = index2 + 4; i < message.Length - 3; i++) - { - if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff && - message[i + 3] == 0x00) - { - index3 = i; - break; - } - } - - var tagBytes = new byte[index - 1]; - Array.Copy(message, 1, tagBytes, 0, tagBytes.Length); - var tag = Encoding.UTF8.GetString(tagBytes); - var splitBytes = new byte[index2 - index - 4]; - Array.Copy(message, index + 4, splitBytes, 0, splitBytes.Length); - var split = Encoding.UTF8.GetString(splitBytes); - var typeBytes = new byte[index3 - index2 - 4]; - Array.Copy(message, index2 + 4, typeBytes, 0, typeBytes.Length); - var type = Type.GetType(Encoding.UTF8.GetString(typeBytes)); - var valueBytes = new byte[message.Length - index3 - 4]; - Array.Copy(message, index3 + 4, valueBytes, 0, valueBytes.Length); - int mainpos = 0, subpos = 0; - var value = BigEndianValueHelper.Instance.GetValue(valueBytes, ref mainpos, ref subpos, type); + var tag = message.Tag; + var split = message.Split; + var value = message.SetValue; var rootDirectory = await Client.ExploreFolderAsync(""); - var tagSplit = SplitTag(tag, split[0]); - var answerTag = await SearchTag(tagSplit, split[0], 0, rootDirectory); + var tagSplit = SplitTag(tag, split); + var answerTag = await SearchTag(tagSplit, split, 0, rootDirectory); if (answerTag != null) { try @@ -173,17 +132,30 @@ namespace Modbus.Net.OPC catch (Exception e) { AddInfo("opc write exception:" + e.Message); - return new byte[] { 0 }; - } - return new byte[] {1}; + return new OpcParamOut() + { + Success = false + }; + } + return new OpcParamOut() + { + Success = true + }; } - return new byte[] {0}; + return new OpcParamOut() + { + Success = false + }; } } catch (Exception e) { AddInfo("opc client exception:" + e.Message); - return Encoding.ASCII.GetBytes("NoData"); + return new OpcParamOut() + { + Success = false, + Value = Encoding.ASCII.GetBytes("NoData") + }; } } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs index 11ec17d..2307645 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs @@ -5,7 +5,7 @@ namespace Modbus.Net.OPC /// /// Opc Da协议连接器 /// - public class OpcDaProtocalLinker : ProtocalLinker + public class OpcDaProtocalLinker : OpcProtocalLinker { public OpcDaProtocalLinker() : this(ConfigurationManager.OpcDaHost) { @@ -15,14 +15,5 @@ namespace Modbus.Net.OPC { BaseConnector = OpcDaConnector.Instance(host); } - - public override bool? CheckRight(byte[] content) - { - if (content != null && content.Length == 6 && Encoding.ASCII.GetString(content) == "NoData") - { - return null; - } - return base.CheckRight(content); - } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs index 5a3025a..119b088 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs @@ -5,7 +5,7 @@ namespace Modbus.Net.OPC /// /// Opc协议 /// - public abstract class OpcProtocal : BaseProtocal + public abstract class OpcProtocal : BaseProtocal> { protected OpcProtocal() : base(0, 0, Endian.BigEndianLsb) { @@ -16,14 +16,14 @@ namespace Modbus.Net.OPC public class ReadRequestOpcInputStruct : IInputStruct { - public ReadRequestOpcInputStruct(string tag, string split) + public ReadRequestOpcInputStruct(string tag, char split) { Tag = tag; Split = split; } public string Tag { get; } - public string Split { get; } + public char Split { get; } } public class ReadRequestOpcOutputStruct : IOutputStruct @@ -36,17 +36,22 @@ namespace Modbus.Net.OPC public byte[] GetValue { get; private set; } } - public class ReadRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit + public class ReadRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit { - public override byte[] Format(IInputStruct message) + public override OpcParamIn Format(IInputStruct message) { var r_message = (ReadRequestOpcInputStruct) message; - return Format((byte) 0x00, Encoding.UTF8.GetBytes(r_message.Tag), 0x00ffff00, Encoding.UTF8.GetBytes(r_message.Split)); + return new OpcParamIn() + { + IsRead = true, + Tag = r_message.Tag, + Split = r_message.Split + }; } - public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) + public override IOutputStruct Unformat(OpcParamOut messageBytes, ref int pos) { - return new ReadRequestOpcOutputStruct(messageBytes); + return new ReadRequestOpcOutputStruct(messageBytes.Value); } } @@ -56,7 +61,7 @@ namespace Modbus.Net.OPC public class WriteRequestOpcInputStruct : IInputStruct { - public WriteRequestOpcInputStruct(string tag, string split, object setValue) + public WriteRequestOpcInputStruct(string tag, char split, object setValue) { Tag = tag; Split = split; @@ -64,7 +69,7 @@ namespace Modbus.Net.OPC } public string Tag { get; } - public string Split { get; } + public char Split { get; } public object SetValue { get; } } @@ -78,20 +83,23 @@ namespace Modbus.Net.OPC public bool WriteResult { get; private set; } } - public class WriteRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit + public class WriteRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit { - public override byte[] Format(IInputStruct message) + public override OpcParamIn Format(IInputStruct message) { var r_message = (WriteRequestOpcInputStruct) message; - var tag = Encoding.UTF8.GetBytes(r_message.Tag); - var fullName = Encoding.UTF8.GetBytes(r_message.SetValue.GetType().FullName); - var split = Encoding.UTF8.GetBytes(r_message.Split); - return Format((byte) 0x01, tag, 0x00ffff00, split, 0x00ffff00, fullName, 0x00ffff00, r_message.SetValue); + return new OpcParamIn() + { + IsRead = false, + Tag = r_message.Tag, + Split = r_message.Split, + SetValue = r_message.SetValue + }; } - public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) + public override IOutputStruct Unformat(OpcParamOut messageBytes, ref int pos) { - var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); + var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes.Value, ref pos); var ans = ansByte != 0; return new WriteRequestOpcOutputStruct(ans); } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs new file mode 100644 index 0000000..352e534 --- /dev/null +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Modbus.Net.OPC +{ + /// + /// Opc协议连接器 + /// + public abstract class OpcProtocalLinker : ProtocalLinker + { + public override bool? CheckRight(OpcParamOut content) + { + if (content == null || !content.Success) return false; + if (content.Value.Length == 6 && Encoding.ASCII.GetString(content.Value) == "NoData") + { + return null; + } + return base.CheckRight(content); + } + } +} diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs index 46673ee..dd090e5 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs @@ -9,7 +9,7 @@ namespace Modbus.Net.OPC /// /// Opc Da协议连接器 /// - public class OpcUaProtocalLinker : ProtocalLinker + public class OpcUaProtocalLinker : OpcProtocalLinker { public OpcUaProtocalLinker() : this(ConfigurationManager.OpcUaHost) { @@ -19,14 +19,5 @@ namespace Modbus.Net.OPC { BaseConnector = OpcUaConnector.Instance(host); } - - public override bool? CheckRight(byte[] content) - { - if (content != null && content.Length == 6 && Encoding.ASCII.GetString(content) == "NoData") - { - return null; - } - return base.CheckRight(content); - } } } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index 18e3fa3..137637b 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Modbus.Net.OPC { - public abstract class OpcUtility : BaseUtility + public abstract class OpcUtility : BaseUtility { protected OpcUtility(string connectionString) : base(0, 0) { @@ -30,7 +30,7 @@ namespace Modbus.Net.OPC try { var split = GetSeperator?.Invoke() ?? '/'; - var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, split.ToString()); + var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, split); var readRequestOpcOutputStruct = await Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct); @@ -47,7 +47,7 @@ namespace Modbus.Net.OPC try { var split = GetSeperator?.Invoke() ?? '/'; - var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, split.ToString(), setContents[0]); + var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, split, setContents[0]); var writeRequestOpcOutputStruct = await Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestOpcProtocal)], writeRequestOpcInputStruct); diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index b367f3a..10f8bdc 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -200,7 +200,7 @@ namespace Modbus.Net /// /// 设备的连接器 /// - protected BaseUtility BaseUtility { get; set; } + public IUtilityProperty BaseUtility { get; protected set; } /// /// 设备的Id @@ -254,7 +254,7 @@ namespace Modbus.Net //获取数据 var datas = await - BaseUtility.GetDatasAsync( + BaseUtility.InvokeUtilityMethod>("GetDatasAsync", AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, communicateAddress.SubAddress), (int) @@ -454,7 +454,7 @@ namespace Modbus.Net var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address); - var datasReturn = await BaseUtility.GetDatasAsync( + var datasReturn = await BaseUtility.InvokeUtilityMethod>("GetDatasAsync", AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0), (int) Math.Ceiling(communicateAddress.GetCount* @@ -544,7 +544,7 @@ namespace Modbus.Net } //写入数据 await - BaseUtility.SetDatasAsync(addressStart, + BaseUtility.InvokeUtilityMethod>("SetDatasAsync",addressStart, valueHelper.ByteArrayToObjectArray(datas, new KeyValuePair(communicateAddress.DataType, communicateAddress.GetCount))); } @@ -580,27 +580,6 @@ 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.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) - .Invoke(BaseUtility, parameters); - return (TReturnType) returnValue; - } - throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口"); - } - /// /// 调用Machine中的方法 /// @@ -865,6 +844,11 @@ namespace Modbus.Net /// bool KeepConnect { get; set; } + /// + /// 设备的连接器 + /// + IUtilityProperty BaseUtility { get; } + /// /// 调用Machine中的方法 /// @@ -877,15 +861,10 @@ namespace Modbus.Net params object[] parameters) where TMachineMethod : IMachineMethod; /// - /// 调用Utility中的方法 + /// 连接设备 /// - /// Utility实现的接口名称 - /// 返回值的类型 - /// 方法的名称 - /// 方法的参数 - /// - TReturnType InvokeUtilityMethod(string methodName, - params object[] parameters) where TUtilityMethod : IUtilityMethod; + /// 是否连接成功 + bool Connect(); /// /// 连接设备 diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 4b473bc..1d7101d 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -8,66 +8,18 @@ namespace Modbus.Net /// /// 基本协议 /// - public abstract class BaseProtocal + public abstract class BaseProtocal : BaseProtocal { - /// - /// 构造器 - /// - protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian) - { - Endian = endian; - Protocals = new Dictionary(); - SlaveAddress = slaveAddress; - MasterAddress = masterAddress; - } - - protected Endian Endian { get; set; } - - public byte SlaveAddress { get; set; } - public byte MasterAddress { get; set; } - /// /// 协议的连接器 /// - public ProtocalLinker ProtocalLinker { get; protected set; } + public new ProtocalLinker ProtocalLinker { get; set; } /// - /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 + /// 构造器 /// - /// 协议的类的GetType - /// 协议的实例 - public ProtocalUnit this[Type type] + protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { - get - { - var protocalName = type.FullName; - if (Protocals.ContainsKey(protocalName)) - { - return Protocals[protocalName]; - } - //自动寻找存在的协议并将其加载 - var protocalUnit = - Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as ProtocalUnit; - if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容"); - protocalUnit.Endian = Endian; - Register(protocalUnit); - return Protocals[protocalName]; - } - } - - /// - /// 协议集合 - /// - protected Dictionary Protocals { get; } - - /// - /// 注册一个协议 - /// - /// 需要注册的协议 - protected void Register(ProtocalUnit linkProtocal) - { - if (linkProtocal == null) return; - Protocals.Add(linkProtocal.GetType().FullName, linkProtocal); } /// @@ -85,7 +37,7 @@ namespace Modbus.Net /// /// 写入的内容,使用对象数组描述 /// 从设备获取的字节流 - public virtual async Task SendReceiveAsync(params object[] content) + public override async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) { @@ -97,6 +49,72 @@ namespace Modbus.Net } return null; } + } + + /// + /// 基本协议 + /// + public abstract class BaseProtocal where TProtocalUnit : ProtocalUnit + { + /// + /// 构造器 + /// + protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian) + { + Endian = endian; + Protocals = new Dictionary(); + SlaveAddress = slaveAddress; + MasterAddress = masterAddress; + } + + protected Endian Endian { get; set; } + + public byte SlaveAddress { get; set; } + public byte MasterAddress { get; set; } + + /// + /// 协议的连接器 + /// + public ProtocalLinker ProtocalLinker { get; protected set; } + + /// + /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 + /// + /// 协议的类的GetType + /// 协议的实例 + public TProtocalUnit this[Type type] + { + get + { + var protocalName = type.FullName; + if (Protocals.ContainsKey(protocalName)) + { + return Protocals[protocalName]; + } + //自动寻找存在的协议并将其加载 + var protocalUnit = + Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; + if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容"); + protocalUnit.Endian = Endian; + Register(protocalUnit); + return Protocals[protocalName]; + } + } + + /// + /// 协议集合 + /// + protected Dictionary Protocals { get; } + + /// + /// 注册一个协议 + /// + /// 需要注册的协议 + protected void Register(TProtocalUnit linkProtocal) + { + if (linkProtocal == null) return; + Protocals.Add(linkProtocal.GetType().FullName, linkProtocal); + } /// /// 发送协议,通过传入需要使用的协议内容和输入结构 @@ -104,7 +122,7 @@ namespace Modbus.Net /// 协议的实例 /// 输入信息的结构化描述 /// 输出信息的结构化描述 - public virtual IOutputStruct SendReceive(ProtocalUnit unit, IInputStruct content) + public virtual IOutputStruct SendReceive(TProtocalUnit unit, IInputStruct content) { return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); } @@ -116,7 +134,7 @@ namespace Modbus.Net /// 输入信息的结构化描述 /// 输出信息的结构化描述 /// IOutputStruct的具体类型 - public virtual T SendReceive(ProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct + public virtual T SendReceive(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct { return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); } @@ -127,7 +145,7 @@ namespace Modbus.Net /// 协议的实例 /// 输入信息的结构化描述 /// 输出信息的结构化描述 - public virtual async Task SendReceiveAsync(ProtocalUnit unit, IInputStruct content) + public virtual async Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content) { return await SendReceiveAsync(unit, content); } @@ -139,13 +157,13 @@ namespace Modbus.Net /// 输入信息的结构化描述 /// 输出信息的结构化描述 /// IOutputStruct的具体类型 - public virtual async Task SendReceiveAsync(ProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct + public virtual async Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct { var t = 0; var formatContent = unit.Format(content); if (formatContent != null) { - byte[] receiveContent; + TParamOut receiveContent; //如果为特别处理协议的话,跳过协议扩展收缩 if (unit is ISpecialProtocalUnit) { @@ -163,6 +181,11 @@ namespace Modbus.Net return null; } + public virtual async Task SendReceiveAsync(params object[] content) + { + throw new NotImplementedException(); + } + /// /// 协议连接开始 /// diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index a88228e..085ed67 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -1,28 +1,59 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Threading.Tasks; +/// +/// 端格式 +/// public enum Endian { + /// + /// 小端 + /// LittleEndianLsb, + /// + /// 大端-小端位 + /// BigEndianLsb, + /// + /// 大端-大端位 + /// BigEndianMsb } namespace Modbus.Net { - + /// + /// 基础Api入口 + /// + public abstract class BaseUtility : BaseUtility + { + /// + /// 构造器 + /// + protected BaseUtility(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress) + { + + } + + /// + /// 协议收发主体 + /// + protected new BaseProtocal Wrapper; + + } /// /// 基础Api入口 /// - public abstract class BaseUtility : IUtilityData + public abstract class BaseUtility : IUtilityProperty, IUtilityData { /// /// 协议收发主体 /// - protected BaseProtocal Wrapper; + protected BaseProtocal> Wrapper; /// /// 构造器 @@ -34,9 +65,18 @@ namespace Modbus.Net AddressTranslator = new AddressTranslatorBase(); } + /// + /// 连接字符串 + /// protected string ConnectionString { get; set; } + /// + /// 从站号 + /// public byte SlaveAddress { get; set; } + /// + /// 主站号 + /// public byte MasterAddress { get; set; } /// @@ -241,5 +281,80 @@ namespace Modbus.Net { return Wrapper.Disconnect(); } + + /// + /// 调用Utility中的方法 + /// + /// Utility实现的接口名称 + /// 返回值的类型 + /// 方法的名称 + /// 方法的参数 + /// + public TReturnType InvokeUtilityMethod(string methodName, + params object[] parameters) where TUtilityMethod : IUtilityMethod + { + if (this is TUtilityMethod) + { + Type t = typeof(TUtilityMethod); + object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) + .Invoke(this, parameters); + return (TReturnType)returnValue; + } + throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口"); + } + } + + /// + /// Api入口的抽象 + /// + public interface IUtilityProperty + { + /// + /// 协议是否遵循小端格式 + /// + Endian Endian { get; } + + /// + /// 设备是否已经连接 + /// + bool IsConnected { get; } + /// + /// 标识设备的连接关键字 + /// + string ConnectionToken { get; } + + /// + /// 地址翻译器 + /// + AddressTranslator AddressTranslator { get; set; } + + /// + /// 连接设备 + /// + /// 设备是否连接成功 + bool Connect(); + + /// + /// 连接设备 + /// + /// 设备是否连接成功 + Task ConnectAsync(); + + /// + /// 断开设备 + /// + /// 设备是否断开成功 + bool Disconnect(); + + /// + /// 调用Utility中的方法 + /// + /// Utility实现的接口名称 + /// 返回值的类型 + /// 方法的名称 + /// 方法的参数 + /// + TReturnType InvokeUtilityMethod(string methodName, + params object[] parameters) where TUtilityMethod : IUtilityMethod; } } \ 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 eca6262..0fcad73 100644 --- a/Modbus.Net/src/Base.Common/IProtocalFormatting.cs +++ b/Modbus.Net/src/Base.Common/IProtocalFormatting.cs @@ -3,14 +3,22 @@ /// /// 协议转换的接口 /// - public interface IProtocalFormatting + public interface IProtocalFormatting : IProtocalFormatting + { + + } + + /// + /// 协议转换的接口 + /// + public interface IProtocalFormatting { /// /// 从输入结构格式化 /// /// 结构化的输入数据 /// 格式化后的字节流 - byte[] Format(IInputStruct message); + TParamIn Format(IInputStruct message); /// /// 从对象的参数数组格式化 @@ -25,6 +33,15 @@ /// 返回数据的字节流 /// 转换标记位 /// 结构化的输出数据 - IOutputStruct Unformat(byte[] messageBytes, ref int pos); + IOutputStruct Unformat(TParamOut messageBytes, ref int pos); + + /// + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// IOutputStruct的具体类型 + /// 结构化的输出数据 + T Unformat(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct; } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index 5a244b0..1ca94be 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -7,9 +7,72 @@ namespace Modbus.Net /// /// 基本的协议连接器 /// - public abstract class ProtocalLinker + public abstract class ProtocalLinker : ProtocalLinker { - protected BaseConnector BaseConnector; + protected new BaseConnector BaseConnector; + + /// + /// 发送并接收数据 + /// + /// 发送协议的内容 + /// 接收协议的内容 + public override async Task SendReceiveAsync(byte[] content) + { + var extBytes = BytesExtend(content); + var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); + return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes); + } + + /// + /// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议 + /// + /// 发送协议的内容 + /// 接收协议的内容 + public override async Task SendReceiveWithoutExtAndDecAsync(byte[] content) + { + //发送数据 + var receiveBytes = await BaseConnector.SendMsgAsync(content); + //容错处理 + var checkRight = CheckRight(receiveBytes); + return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes); + //返回字符 + } + + /// + /// 协议内容扩展,发送时根据需要扩展 + /// + /// 扩展前的基本协议内容 + /// 扩展后的协议内容 + public override byte[] BytesExtend(byte[] content) + { + //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。 + var bytesExtend = + Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as + IProtocalLinkerBytesExtend; + return bytesExtend?.BytesExtend(content); + } + + /// + /// 协议内容缩减,接收时根据需要缩减 + /// + /// 缩减前的完整协议内容 + /// 缩减后的协议内容 + public override byte[] BytesDecact(byte[] content) + { + //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。 + var bytesExtend = + Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as + IProtocalLinkerBytesExtend; + return bytesExtend?.BytesDecact(content); + } + } + + /// + /// 基本的协议连接器 + /// + public abstract class ProtocalLinker + { + protected BaseConnector BaseConnector; public string ConnectionToken => BaseConnector.ConnectionToken; @@ -50,7 +113,7 @@ namespace Modbus.Net /// /// 发送协议的内容 /// 接收协议的内容 - public virtual byte[] SendReceive(byte[] content) + public virtual TParamOut SendReceive(TParamIn content) { return AsyncHelper.RunSync(() => SendReceiveAsync(content)); } @@ -60,11 +123,12 @@ namespace Modbus.Net /// /// 发送协议的内容 /// 接收协议的内容 - public virtual async Task SendReceiveAsync(byte[] content) + public virtual async Task SendReceiveAsync(TParamIn content) { var extBytes = BytesExtend(content); var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); - return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes); + if (receiveBytes != null) return receiveBytes; + throw new NullReferenceException(); } /// @@ -72,7 +136,7 @@ namespace Modbus.Net /// /// 发送协议的内容 /// 接收协议的内容 - public virtual byte[] SendReceiveWithoutExtAndDec(byte[] content) + public virtual TParamOut SendReceiveWithoutExtAndDec(TParamIn content) { return AsyncHelper.RunSync(() => SendReceiveWithoutExtAndDecAsync(content)); } @@ -82,14 +146,15 @@ namespace Modbus.Net /// /// 发送协议的内容 /// 接收协议的内容 - public virtual async Task SendReceiveWithoutExtAndDecAsync(byte[] content) + public virtual async Task SendReceiveWithoutExtAndDecAsync(TParamIn content) { //发送数据 var receiveBytes = await BaseConnector.SendMsgAsync(content); //容错处理 var checkRight = CheckRight(receiveBytes); - return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes); //返回字符 + if (checkRight == true) return receiveBytes; + throw new NullReferenceException(); } /// @@ -97,7 +162,7 @@ namespace Modbus.Net /// /// 接收协议的内容 /// 协议是否是正确的 - public virtual bool? CheckRight(byte[] content) + public virtual bool? CheckRight(TParamOut content) { if (content != null) return true; Disconnect(); @@ -109,13 +174,9 @@ namespace Modbus.Net /// /// 扩展前的基本协议内容 /// 扩展后的协议内容 - public byte[] BytesExtend(byte[] content) + public virtual TParamIn BytesExtend(TParamIn content) { - //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。 - var bytesExtend = - Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as - IProtocalLinkerBytesExtend; - return bytesExtend?.BytesExtend(content); + throw new NotImplementedException(); } /// @@ -123,13 +184,9 @@ namespace Modbus.Net /// /// 缩减前的完整协议内容 /// 缩减后的协议内容 - public byte[] BytesDecact(byte[] content) + public virtual TParamOut BytesDecact(TParamOut content) { - //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。 - var bytesExtend = - Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as - IProtocalLinkerBytesExtend; - return bytesExtend?.BytesDecact(content); + throw new NotImplementedException(); } } } \ 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 46aff85..33b7506 100644 --- a/Modbus.Net/src/Base.Common/ProtocalUnit.cs +++ b/Modbus.Net/src/Base.Common/ProtocalUnit.cs @@ -5,7 +5,15 @@ namespace Modbus.Net /// /// 协议单元 /// - public abstract class ProtocalUnit : IProtocalFormatting + public abstract class ProtocalUnit : ProtocalUnit + { + + } + + /// + /// 协议单元 + /// + public abstract class ProtocalUnit : IProtocalFormatting { /// /// 是否为小端格式 @@ -17,7 +25,7 @@ namespace Modbus.Net /// s /// 结构化的输入数据 /// 格式化后的字节流 - public abstract byte[] Format(IInputStruct message); + public abstract TParamIn Format(IInputStruct message); /// /// 从对象的参数数组格式化 @@ -35,7 +43,7 @@ namespace Modbus.Net /// 返回数据的字节流 /// 转换标记位 /// 结构化的输出数据 - public abstract IOutputStruct Unformat(byte[] messageBytes, ref int pos); + public abstract IOutputStruct Unformat(TParamOut messageBytes, ref int pos); /// /// 把仪器返回的内容填充到输出结构中 @@ -44,7 +52,7 @@ namespace Modbus.Net /// 转换标记位 /// IOutputStruct的具体类型 /// 结构化的输出数据 - public T Unformat(byte[] messageBytes, ref int pos) where T : class, IOutputStruct + public T Unformat(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct { return Unformat(messageBytes, ref pos) as T; } diff --git a/Samples/TripleAdd/Controllers/HomeController.cs b/Samples/TripleAdd/Controllers/HomeController.cs index fe8fd5d..3f7d401 100644 --- a/Samples/TripleAdd/Controllers/HomeController.cs +++ b/Samples/TripleAdd/Controllers/HomeController.cs @@ -58,8 +58,8 @@ namespace TripleAdd.Controllers new AddressUnit() {Id = "3", Area = "4X", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, new AddressUnit() {Id = "4", Area = "4X", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, }, 2, 0); - machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator); - machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator); + machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator, 100000); + machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator, 100000); } var resultFormat = (await machine.GetDatasAsync(MachineGetDataType.CommunicationTag)).MapGetValuesToSetValues(); return SetValue(new ushort[4] { (ushort)resultFormat["Add1"], (ushort)resultFormat["Add2"], (ushort)resultFormat["Add3"], (ushort)resultFormat["Ans"] }); diff --git a/Tests/Modbus.Net.Tests/MachineMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs index be08009..e6d980a 100644 --- a/Tests/Modbus.Net.Tests/MachineMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -25,9 +25,9 @@ namespace Modbus.Net.Tests public async Task InvokeUtility() { BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); - var success = await baseMachine.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); + var success = await baseMachine.BaseUtility.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); Assert.AreEqual(success, true); - var time = await baseMachine.InvokeUtilityMethod>("GetTimeAsync"); + var time = await baseMachine.BaseUtility.InvokeUtilityMethod>("GetTimeAsync"); Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true); } From 60786eec5aea892fdc6fbff18857c14cceb3e2a6 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 3 May 2017 17:16:32 +0800 Subject: [PATCH 07/62] Fix 1 Add Methods in Opc. --- .../Modbus.Net.OPC/OpcProtocalLinker.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs index 352e534..c042357 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs @@ -11,6 +11,42 @@ namespace Modbus.Net.OPC /// public abstract class OpcProtocalLinker : ProtocalLinker { + /// + /// 发送并接收数据 + /// + /// 发送协议的内容 + /// 接收协议的内容 + public override async Task SendReceiveAsync(OpcParamIn content) + { + var extBytes = BytesExtend(content); + var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); + return receiveBytes == null + ? null + : receiveBytes.Value.Length == 0 ? receiveBytes : BytesDecact(receiveBytes); + } + + /// + /// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议 + /// + /// 发送协议的内容 + /// 接收协议的内容 + public override async Task SendReceiveWithoutExtAndDecAsync(OpcParamIn content) + { + //发送数据 + var receiveBytes = await BaseConnector.SendMsgAsync(content); + //容错处理 + var checkRight = CheckRight(receiveBytes); + return checkRight == null + ? new OpcParamOut {Success = false, Value = new byte[0]} + : (!checkRight.Value ? null : receiveBytes); + //返回字符 + } + + /// + /// 检查接收的数据是否正确 + /// + /// 接收协议的内容 + /// 协议是否是正确的 public override bool? CheckRight(OpcParamOut content) { if (content == null || !content.Success) return false; From 34181621372b12350dd6787da0c029958466c2ea Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 4 May 2017 12:00:07 +0800 Subject: [PATCH 08/62] Fix 2 Add Full Comments And name Fix. --- Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 2 +- Modbus.Net/Modbus.Net/ComProtocalLinker.cs | 15 + Modbus.Net/src/Base.Common/AddressCombiner.cs | 66 ++++ Modbus.Net/src/Base.Common/AddressFormater.cs | 19 ++ .../src/Base.Common/AddressTranslator.cs | 31 +- Modbus.Net/src/Base.Common/BaseMachine.cs | 39 ++- Modbus.Net/src/Base.Common/BaseProtocal.cs | 40 ++- Modbus.Net/src/Base.Common/BaseUtility.cs | 2 +- Modbus.Net/src/Base.Common/CRC16.cs | 34 +- Modbus.Net/src/Base.Common/IMachineMethod.cs | 5 +- Modbus.Net/src/Base.Common/IProtocal.cs | 18 +- .../src/Base.Common/IProtocalFormatting.cs | 2 + Modbus.Net/src/Base.Common/IProtocalLinker.cs | 21 +- .../Base.Common/IProtocalLinkerBytesExtend.cs | 14 +- Modbus.Net/src/Base.Common/IUtilityMethod.cs | 15 +- Modbus.Net/src/Base.Common/ProtocalLinker.cs | 11 +- Modbus.Net/src/Base.Common/ProtocalUnit.cs | 4 + Modbus.Net/src/Base.Common/TaskManager.cs | 4 +- Modbus.Net/src/Base.Common/TcpConnector.cs | 51 ++- .../src/Base.Common/TcpProtocalLinker.cs | 8 + Modbus.Net/src/Base.Common/ValueHelper.cs | 322 ++++++++++++++---- Tests/Modbus.Net.Tests/MachineMethodTest.cs | 12 +- 22 files changed, 596 insertions(+), 139 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index eba6b3c..fac9f5b 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -27,7 +27,7 @@ namespace Modbus.Net.Modbus /// /// Modbus基础Api入口 /// - public class ModbusUtility : BaseUtility, IUtilityTime + public class ModbusUtility : BaseUtility, IUtilityMethodTime { /// /// Modbus协议类型 diff --git a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs index e596f0f..8ddcfc6 100644 --- a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs @@ -7,11 +7,26 @@ namespace Modbus.Net /// public abstract class ComProtocalLinker : ProtocalLinker { + /// + /// 构造器 + /// + /// 波特率 + /// 校验位 + /// 停止位 + /// 数据位 protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits) : this(ConfigurationManager.COM, baudRate, parity, stopBits, dataBits) { } + /// + /// 构造器 + /// + /// 串口端口号 + /// 波特率 + /// 校验位 + /// 停止位 + /// 数据位 protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits) { //初始化连对象 diff --git a/Modbus.Net/src/Base.Common/AddressCombiner.cs b/Modbus.Net/src/Base.Common/AddressCombiner.cs index f60226a..4ad03d5 100644 --- a/Modbus.Net/src/Base.Common/AddressCombiner.cs +++ b/Modbus.Net/src/Base.Common/AddressCombiner.cs @@ -29,6 +29,11 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombinerContinus { + /// + /// 构造函数 + /// + /// 地址转换器 + /// 单个发送协议允许的数据最长长度(字节) public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) : base(addressTranslator, maxLength) { } @@ -39,16 +44,32 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombiner where TKey : IEquatable { + /// + /// 协议的数据最长长度(字节) + /// protected int MaxLength { get; set; } + /// + /// 构造函数 + /// + /// 地址转换器 + /// 单个发送协议允许的数据最长长度(字节) public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) { AddressTranslator = addressTranslator; MaxLength = maxLength; } + /// + /// 地址转换器 + /// protected AddressTranslator AddressTranslator { get; set; } + /// + /// 组合地址 + /// + /// 需要组合的地址 + /// 组合后的地址 public override IEnumerable> Combine(IEnumerable> addresses) { //按从小到大的顺序对地址进行排序 @@ -218,6 +239,11 @@ namespace Modbus.Net /// public class AddressCombinerSingle : AddressCombiner where TKey : IEquatable { + /// + /// 组合地址 + /// + /// 需要组合的地址 + /// 组合后的地址 public override IEnumerable> Combine(IEnumerable> addresses) { return @@ -249,6 +275,12 @@ namespace Modbus.Net /// public class AddressCombinerNumericJump : AddressCombinerNumericJump { + /// + /// 构造函数 + /// + /// 需要跳过的字节个数 + /// 单个协议允许的数据最长长度(字节) + /// 地址转换器 public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator) : base(jumpByteCount, maxLength, addressTranslator) { @@ -260,14 +292,28 @@ namespace Modbus.Net /// public class AddressCombinerNumericJump : AddressCombinerContinus where TKey : IEquatable { + /// + /// 构造函数 + /// + /// 需要跳过的字节个数 + /// 单个协议允许的数据最长长度(字节) + /// 地址转换器 public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator) : base(addressTranslator, maxLength) { JumpNumber = jumpByteCount; } + /// + /// 跳过的地址长度 + /// private int JumpNumber { get; } + /// + /// 组合地址 + /// + /// 需要组合的地址 + /// 组合后的地址 public override IEnumerable> Combine(IEnumerable> addresses) { var continusAddresses = base.Combine(addresses).ToList(); @@ -339,6 +385,12 @@ namespace Modbus.Net /// public class AddressCombinerPercentageJump : AddressCombinerPercentageJump { + /// + /// 构造函数 + /// + /// 允许跳过的字节数除以待组合的地址的字节数的百分比 + /// 单个协议允许的数据最大长度 + /// 地址转换器 public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator) : base(percentage, maxLength, addressTranslator) { @@ -350,6 +402,12 @@ namespace Modbus.Net /// public class AddressCombinerPercentageJump : AddressCombinerContinus where TKey : IEquatable { + /// + /// 构造函数 + /// + /// 允许跳过的字节数除以待组合的地址的字节数的百分比 + /// 单个协议允许的数据最大长度 + /// 地址转换器 public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator) : base(addressTranslator, maxLength) { @@ -357,8 +415,16 @@ namespace Modbus.Net Percentage = percentage; } + /// + /// 跳过的百分比 + /// private double Percentage { get; } + /// + /// 组合地址 + /// + /// 需要组合的地址 + /// 组合后的地址 public override IEnumerable> Combine(IEnumerable> addresses) { var addressUnits = addresses as IList> ?? addresses.ToList(); diff --git a/Modbus.Net/src/Base.Common/AddressFormater.cs b/Modbus.Net/src/Base.Common/AddressFormater.cs index c24307f..111b7c8 100644 --- a/Modbus.Net/src/Base.Common/AddressFormater.cs +++ b/Modbus.Net/src/Base.Common/AddressFormater.cs @@ -5,6 +5,12 @@ /// public abstract class AddressFormater { + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 编码后的地址 public abstract string FormatAddress(string area, int address); /// @@ -22,11 +28,24 @@ /// public class AddressFormaterBase : AddressFormater { + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 编码后的地址 public override string FormatAddress(string area, int address) { return area + ":" + address; } + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 子地址 + /// 编码后的地址 public override string FormatAddress(string area, int address, int subAddress) { return area + ":" + address + ":" + subAddress; diff --git a/Modbus.Net/src/Base.Common/AddressTranslator.cs b/Modbus.Net/src/Base.Common/AddressTranslator.cs index cc09a15..39c1c68 100644 --- a/Modbus.Net/src/Base.Common/AddressTranslator.cs +++ b/Modbus.Net/src/Base.Common/AddressTranslator.cs @@ -7,18 +7,36 @@ namespace Modbus.Net /// public class AddressDef { + /// + /// 地址区域的字符串描述 + /// public string AreaString { get; set; } + /// + /// 地址区域的数字描述 + /// public int Area { get; set; } + /// + /// 地址 + /// public int Address { get; set; } + /// + /// 子地址 + /// public int SubAddress { get; set; } } /// - /// 区域数据定义类 + /// 地址区域数据定义类 /// public class AreaOutputDef { + /// + /// 地址区域的编码 + /// public int Code { get; set; } + /// + /// 地址区域的单个地址占用的字节数 + /// public double AreaWidth { get; set; } } @@ -48,6 +66,12 @@ namespace Modbus.Net /// public class AddressTranslatorBase : AddressTranslator { + /// + /// 地址转换 + /// + /// 地址前地址 + /// 是否为读取,是为读取,否为写入 + /// Key为转换后的地址,Value为辅助码 public override AddressDef AddressTranslate(string address, bool isRead) { int num1, num2, num3; @@ -79,6 +103,11 @@ namespace Modbus.Net throw new FormatException(); } + /// + /// 获取区域中的单个地址占用的字节长度 + /// + /// 区域名称 + /// 字节长度 public override double GetAreaByteLength(string area) { return 1; diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 10f8bdc..80d26c8 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -84,24 +84,48 @@ namespace Modbus.Net Id } + /// + /// 设备 + /// public abstract class BaseMachine : BaseMachine { + /// + /// 构造器 + /// + /// 需要与设备通讯的地址 protected BaseMachine(IEnumerable getAddresses) : base(getAddresses) { } + /// + /// 构造器 + /// + /// 需要与设备通讯的地址 + /// 是否保持连接 protected BaseMachine(IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { } + /// + /// 构造器 + /// + /// 需要与设备通讯的地址 + /// 是否保持连接 + /// 从站地址 + /// 主站地址 protected BaseMachine(IEnumerable getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress) : base(getAddresses, keepConnect, slaveAddress, masterAddress) { } } - public abstract class BaseMachine : IMachineData, IMachineProperty where TKey : IEquatable + /// + /// 设备 + /// + /// 设备的Id类型 + /// 设备中使用的AddressUnit的Id类型 + public abstract class BaseMachine : IMachineMethodData, IMachineProperty where TKey : IEquatable where TUnitKey : IEquatable { private readonly int _maxErrorCount = 3; @@ -254,7 +278,7 @@ namespace Modbus.Net //获取数据 var datas = await - BaseUtility.InvokeUtilityMethod>("GetDatasAsync", + BaseUtility.InvokeUtilityMethod>("GetDatasAsync", AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, communicateAddress.SubAddress), (int) @@ -454,7 +478,7 @@ namespace Modbus.Net var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address); - var datasReturn = await BaseUtility.InvokeUtilityMethod>("GetDatasAsync", + var datasReturn = await BaseUtility.InvokeUtilityMethod>("GetDatasAsync", AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0), (int) Math.Ceiling(communicateAddress.GetCount* @@ -544,7 +568,7 @@ namespace Modbus.Net } //写入数据 await - BaseUtility.InvokeUtilityMethod>("SetDatasAsync",addressStart, + BaseUtility.InvokeUtilityMethod>("SetDatasAsync",addressStart, valueHelper.ByteArrayToObjectArray(datas, new KeyValuePair(communicateAddress.DataType, communicateAddress.GetCount))); } @@ -639,7 +663,7 @@ namespace Modbus.Net } } - public class BaseMachineEqualityComparer : IEqualityComparer> + internal class BaseMachineEqualityComparer : IEqualityComparer> where TKey : IEquatable { public bool Equals(IMachineProperty x, IMachineProperty y) @@ -793,10 +817,7 @@ namespace Modbus.Net public UnitExtend UnitExtend { get; set; } } - /// - /// AddressUnit大小比较 - /// - public struct AddressUnitEqualityComparer : IEqualityComparer> where TKey : IEquatable + internal struct AddressUnitEqualityComparer : IEqualityComparer> where TKey : IEquatable { public bool Equals(AddressUnit x, AddressUnit y) { diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 1d7101d..c4db1f3 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -22,16 +22,6 @@ namespace Modbus.Net { } - /// - /// 发送协议内容并接收,一般方法 - /// - /// 写入的内容,使用对象数组描述 - /// 从设备获取的字节流 - public virtual byte[] SendReceive(params object[] content) - { - return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content)); - } - /// /// 发送协议内容并接收,一般方法 /// @@ -54,7 +44,7 @@ namespace Modbus.Net /// /// 基本协议 /// - public abstract class BaseProtocal where TProtocalUnit : ProtocalUnit + public abstract class BaseProtocal : IProtocal where TProtocalUnit : ProtocalUnit { /// /// 构造器 @@ -67,9 +57,18 @@ namespace Modbus.Net MasterAddress = masterAddress; } + /// + /// 协议的端格式 + /// protected Endian Endian { get; set; } - + + /// + /// 从站地址 + /// public byte SlaveAddress { get; set; } + /// + /// 主站地址 + /// public byte MasterAddress { get; set; } /// @@ -181,7 +180,22 @@ namespace Modbus.Net return null; } - public virtual async Task SendReceiveAsync(params object[] content) + /// + /// 发送协议内容并接收,一般方法 + /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 + public virtual byte[] SendReceive(params object[] content) + { + return AsyncHelper.RunSync(() => SendReceiveAsync(content)); + } + + /// + /// 发送协议内容并接收,一般方法 + /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 + public virtual Task SendReceiveAsync(params object[] content) { throw new NotImplementedException(); } diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index 085ed67..830b401 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -48,7 +48,7 @@ namespace Modbus.Net /// /// 基础Api入口 /// - public abstract class BaseUtility : IUtilityProperty, IUtilityData + public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData { /// /// 协议收发主体 diff --git a/Modbus.Net/src/Base.Common/CRC16.cs b/Modbus.Net/src/Base.Common/CRC16.cs index 2f9dc03..67594dc 100644 --- a/Modbus.Net/src/Base.Common/CRC16.cs +++ b/Modbus.Net/src/Base.Common/CRC16.cs @@ -7,15 +7,27 @@ using System; namespace Modbus.Net { + /// + /// CRC-LRC校验工具 + /// public class Crc16 { private static Crc16 _crc16; + private Crc16() + { + + } + /// /// CRC验证表 /// - public byte[] crc_table = new byte[512]; + private byte[] crc_table = new byte[512]; + /// + /// 获取校验工具实例 + /// + /// public static Crc16 GetInstance() { if (_crc16 == null) @@ -88,12 +100,14 @@ namespace Modbus.Net #endregion + #region LRC验证 + /// /// 取模FF(255) /// 取反+1 /// - /// - /// + /// 待验证的LRC消息 + /// LRC校验是否正确 public bool LrcEfficacy(string message) { var index = message.IndexOf(Environment.NewLine, StringComparison.Ordinal); @@ -176,6 +190,15 @@ namespace Modbus.Net return hexTotal == checkString; } + #endregion + + #region 生成LRC码 + + /// + /// 生成LRC校验码 + /// + /// 需要生成的信息 + /// 生成的校验码 public string GetLRC(byte[] code) { byte sum = 0; @@ -183,9 +206,12 @@ namespace Modbus.Net { sum += b; } - sum = (byte) (~sum + 1); //取反+1 + sum = (byte)(~sum + 1); //取反+1 var lrc = sum.ToString("X2"); return lrc; } + + #endregion + } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IMachineMethod.cs b/Modbus.Net/src/Base.Common/IMachineMethod.cs index cac1f19..c5fc50b 100644 --- a/Modbus.Net/src/Base.Common/IMachineMethod.cs +++ b/Modbus.Net/src/Base.Common/IMachineMethod.cs @@ -6,6 +6,9 @@ using System.Threading.Tasks; namespace Modbus.Net { + /// + /// Machineдӿ + /// public interface IMachineMethod { @@ -14,7 +17,7 @@ namespace Modbus.Net /// /// Machineݶдӿ /// - public interface IMachineData : IMachineMethod + public interface IMachineMethodData : IMachineMethod { /// /// ȡ diff --git a/Modbus.Net/src/Base.Common/IProtocal.cs b/Modbus.Net/src/Base.Common/IProtocal.cs index f7f2f18..b2b4fae 100644 --- a/Modbus.Net/src/Base.Common/IProtocal.cs +++ b/Modbus.Net/src/Base.Common/IProtocal.cs @@ -6,23 +6,27 @@ using System.Threading.Tasks; namespace Modbus.Net { - public interface IProtocal + /// + /// 协议接口 + /// + /// 向Connector传入的类型 + /// 从Connector返回的类型 + /// 协议单元的类型 + public interface IProtocal where TProtocalUnit : IProtocalFormatting { /// /// 发送协议内容并接收,一般方法 /// - /// 是否是小端格式 /// 写入的内容,使用对象数组描述 /// 从设备获取的字节流 - byte[] SendReceive(bool isLittleEndian, params object[] content); + byte[] SendReceive(params object[] content); /// /// 发送协议内容并接收,一般方法 /// - /// 是否是小端格式 /// 写入的内容,使用对象数组描述 /// 从设备获取的字节流 - Task SendReceiveAsync(bool isLittleEndian, params object[] content); + Task SendReceiveAsync(params object[] content); /// /// 发送协议,通过传入需要使用的协议内容和输入结构 @@ -30,7 +34,7 @@ namespace Modbus.Net /// 协议的实例 /// 输入信息的结构化描述 /// 输出信息的结构化描述 - IOutputStruct SendReceive(ProtocalUnit unit, IInputStruct content); + IOutputStruct SendReceive(TProtocalUnit unit, IInputStruct content); /// /// 发送协议,通过传入需要使用的协议内容和输入结构 @@ -38,6 +42,6 @@ namespace Modbus.Net /// 协议的实例 /// 输入信息的结构化描述 /// 输出信息的结构化描述 - Task SendReceiveAsync(ProtocalUnit unit, IInputStruct content); + Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content); } } diff --git a/Modbus.Net/src/Base.Common/IProtocalFormatting.cs b/Modbus.Net/src/Base.Common/IProtocalFormatting.cs index 0fcad73..d494e8c 100644 --- a/Modbus.Net/src/Base.Common/IProtocalFormatting.cs +++ b/Modbus.Net/src/Base.Common/IProtocalFormatting.cs @@ -11,6 +11,8 @@ /// /// 协议转换的接口 /// + /// 向Connector传入的数据类型 + /// 从Connector返回的数据类型 public interface IProtocalFormatting { /// diff --git a/Modbus.Net/src/Base.Common/IProtocalLinker.cs b/Modbus.Net/src/Base.Common/IProtocalLinker.cs index 9b03f50..94633ad 100644 --- a/Modbus.Net/src/Base.Common/IProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/IProtocalLinker.cs @@ -6,55 +6,60 @@ using System.Threading.Tasks; namespace Modbus.Net { - public interface IProtocalLinker + /// + /// 协议连接器接口 + /// + /// 向Connector传入的数据类型 + /// 从Connector返回的数据类型 + public interface IProtocalLinker { /// /// 发送并接收数据 /// /// 发送协议的内容 /// 接收协议的内容 - byte[] SendReceive(byte[] content); + TParamOut SendReceive(TParamIn content); /// /// 发送并接收数据 /// /// 发送协议的内容 /// 接收协议的内容 - Task SendReceiveAsync(byte[] content); + Task SendReceiveAsync(TParamIn content); /// /// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议 /// /// 发送协议的内容 /// 接收协议的内容 - byte[] SendReceiveWithoutExtAndDec(byte[] content); + TParamOut SendReceiveWithoutExtAndDec(TParamIn content); /// /// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议 /// /// 发送协议的内容 /// 接收协议的内容 - Task SendReceiveWithoutExtAndDecAsync(byte[] content); + Task SendReceiveWithoutExtAndDecAsync(TParamIn content); /// /// 检查接收的数据是否正确 /// /// 接收协议的内容 /// 协议是否是正确的 - bool? CheckRight(byte[] content); + bool? CheckRight(TParamOut content); /// /// 协议内容扩展,发送时根据需要扩展 /// /// 扩展前的基本协议内容 /// 扩展后的协议内容 - byte[] BytesExtend(byte[] content); + TParamIn BytesExtend(TParamIn content); /// /// 协议内容缩减,接收时根据需要缩减 /// /// 缩减前的完整协议内容 /// 缩减后的协议内容 - byte[] BytesDecact(byte[] content); + TParamOut BytesDecact(TParamOut content); } } diff --git a/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs b/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs index 4dafffe..77f168e 100644 --- a/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs +++ b/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs @@ -3,20 +3,28 @@ /// /// 协议字节伸缩 /// - public interface IProtocalLinkerBytesExtend + public interface IProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend + { + + } + + /// + /// 协议字节伸缩 + /// + public interface IProtocalLinkerBytesExtend { /// /// 协议扩展,协议内容发送前调用 /// /// 扩展前的原始协议内容 /// 扩展后的协议内容 - byte[] BytesExtend(byte[] content); + TParamIn BytesExtend(TParamIn content); /// /// 协议收缩,协议内容接收后调用 /// /// 收缩前的完整协议内容 /// 收缩后的协议内容 - byte[] BytesDecact(byte[] content); + TParamOut BytesDecact(TParamOut content); } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IUtilityMethod.cs b/Modbus.Net/src/Base.Common/IUtilityMethod.cs index 8e6bca3..a6b9deb 100644 --- a/Modbus.Net/src/Base.Common/IUtilityMethod.cs +++ b/Modbus.Net/src/Base.Common/IUtilityMethod.cs @@ -6,15 +6,18 @@ using System.Threading.Tasks; namespace Modbus.Net { + /// + /// Utility方法读写接口 + /// public interface IUtilityMethod { } /// - /// Utility的数据读写接口 + /// Utility的数据读写接口 /// - public interface IUtilityData : IUtilityMethod + public interface IUtilityMethodData : IUtilityMethod { /// /// 获取数据 @@ -91,19 +94,19 @@ namespace Modbus.Net } /// - /// Utility的时间读写接口 + /// Utility的时间读写接口 /// - public interface IUtilityTime : IUtilityMethod + public interface IUtilityMethodTime : IUtilityMethod { /// - /// 获取PLC时间 + /// 获取PLC时间 /// /// PLC时间 Task GetTimeAsync(); /// - /// 设置PLC时间 + /// 设置PLC时间 /// /// 设置PLC时间 /// 设置是否成功 diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index 1ca94be..0d2bf45 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -9,6 +9,9 @@ namespace Modbus.Net /// public abstract class ProtocalLinker : ProtocalLinker { + /// + /// 传输连接器 + /// protected new BaseConnector BaseConnector; /// @@ -70,10 +73,16 @@ namespace Modbus.Net /// /// 基本的协议连接器 /// - public abstract class ProtocalLinker + public abstract class ProtocalLinker : IProtocalLinker { + /// + /// 传输连接器 + /// protected BaseConnector BaseConnector; + /// + /// 通讯字符串 + /// public string ConnectionToken => BaseConnector.ConnectionToken; /// diff --git a/Modbus.Net/src/Base.Common/ProtocalUnit.cs b/Modbus.Net/src/Base.Common/ProtocalUnit.cs index 33b7506..f10c579 100644 --- a/Modbus.Net/src/Base.Common/ProtocalUnit.cs +++ b/Modbus.Net/src/Base.Common/ProtocalUnit.cs @@ -95,6 +95,10 @@ namespace Modbus.Net /// public class ProtocalErrorException : Exception { + /// + /// 构造函数 + /// + /// public ProtocalErrorException(string message) : base(message) { diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index cd73294..f6058ec 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -725,7 +725,7 @@ namespace Modbus.Net machine = _machines.FirstOrDefault(p => p.ConnectionToken == connectionToken); } if (machine == null) return false; - return await machine.InvokeMachineMethod>("SetDatasAsync", SetDataType, values); + return await machine.InvokeMachineMethod>("SetDatasAsync", SetDataType, values); } /// @@ -799,7 +799,7 @@ namespace Modbus.Net cts.CancelAfter(TimeSpan.FromSeconds(_getCycle)); //读取数据 var ans = - await machine.InvokeMachineMethod>>("GetDatasAsync", + await machine.InvokeMachineMethod>>("GetDatasAsync", GetDataType).WithCancellation(cts.Token); if (!machine.IsConnected) { diff --git a/Modbus.Net/src/Base.Common/TcpConnector.cs b/Modbus.Net/src/Base.Common/TcpConnector.cs index 62e14bf..2b354e3 100644 --- a/Modbus.Net/src/Base.Common/TcpConnector.cs +++ b/Modbus.Net/src/Base.Common/TcpConnector.cs @@ -10,12 +10,19 @@ namespace Modbus.Net /// public class SocketMessageEventArgs : EventArgs { + /// + /// 构造器 + /// + /// 需要返回的信息 public SocketMessageEventArgs(byte[] message) { Message = message; } - public byte[] Message { get; set; } + /// + /// 返回的信息 + /// + public byte[] Message { get; } } /// @@ -39,6 +46,12 @@ namespace Modbus.Net private bool m_disposed; + /// + /// 构造器 + /// + /// Ip地址 + /// 端口 + /// 超时时间 public TcpConnector(string ipaddress, int port, int timeoutTime) { _host = ipaddress; @@ -46,8 +59,14 @@ namespace Modbus.Net TimeoutTime = timeoutTime; } + /// + /// 连接关键字 + /// public override string ConnectionToken => _host; + /// + /// 超时时间 + /// public int TimeoutTime { get { return _timeoutTime; } @@ -61,6 +80,9 @@ namespace Modbus.Net } } + /// + /// 是否已经连接 + /// public override bool IsConnected => _socketClient?.Client != null && _socketClient.Connected; /// @@ -106,11 +128,19 @@ namespace Modbus.Net Dispose(false); } + /// + /// 连接 + /// + /// 是否连接成功 public override bool Connect() { return AsyncHelper.RunSync(ConnectAsync); } + /// + /// 连接 + /// + /// 是否连接成功 public override async Task ConnectAsync() { if (_socketClient != null) @@ -150,6 +180,10 @@ namespace Modbus.Net } } + /// + /// 断开 + /// + /// 是否断开成功 public override bool Disconnect() { if (_socketClient == null) @@ -183,6 +217,11 @@ namespace Modbus.Net Console.WriteLine(message); } + /// + /// 发送数据,不需要返回任何值 + /// + /// 发送的信息 + /// 是否发送成功 public override bool SendMsgWithoutReturn(byte[] message) { return AsyncHelper.RunSync(() => SendMsgWithoutReturnAsync(message)); @@ -219,6 +258,11 @@ namespace Modbus.Net } } + /// + /// 发送数据,需要返回 + /// + /// 发送的数据 + /// 是否发送成功 public override byte[] SendMsg(byte[] message) { return AsyncHelper.RunSync(() => SendMsgAsync(message)); @@ -256,6 +300,11 @@ namespace Modbus.Net } } + /// + /// 接收返回消息 + /// + /// Network Stream + /// 返回的消息 protected async Task ReceiveAsync(NetworkStream stream) { try diff --git a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs index a117c00..cb1077a 100644 --- a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs @@ -5,10 +5,18 @@ /// public abstract class TcpProtocalLinker : ProtocalLinker { + /// + /// 构造器 + /// protected TcpProtocalLinker() : this(ConfigurationManager.IP, int.Parse(ConfigurationManager.ModbusPort)) { } + /// + /// 构造器 + /// + /// Ip地址 + /// 端口 protected TcpProtocalLinker(string ip, int port) { //初始化连接对象 diff --git a/Modbus.Net/src/Base.Common/ValueHelper.cs b/Modbus.Net/src/Base.Common/ValueHelper.cs index e534bfb..c5c953e 100644 --- a/Modbus.Net/src/Base.Common/ValueHelper.cs +++ b/Modbus.Net/src/Base.Common/ValueHelper.cs @@ -7,10 +7,13 @@ using System.Text; namespace Modbus.Net { /// - /// 值与字节数组之间转换的辅助类,这是一个Singleton类 + /// 值与字节数组之间转换的辅助类(小端格式),这是一个Singleton类 /// public class ValueHelper { + /// + /// 兼容数据类型对应的字节长度 + /// public Dictionary ByteLength = new Dictionary { {"System.Boolean", 0.125}, @@ -25,6 +28,9 @@ namespace Modbus.Net {"System.Double", 8} }; + /// + /// 构造器 + /// protected ValueHelper() { } @@ -34,6 +40,9 @@ namespace Modbus.Net /// public static bool LittleEndian => true; + /// + /// 协议中的比特位内容构造是否小端的,默认是小端构造协议。 + /// public static bool LittleEndianBit => true; /// @@ -49,8 +58,8 @@ namespace Modbus.Net /// /// 将short数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(short value) { return BitConverter.GetBytes(value); @@ -59,8 +68,8 @@ namespace Modbus.Net /// /// 将int数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(int value) { return BitConverter.GetBytes(value); @@ -69,8 +78,8 @@ namespace Modbus.Net /// /// 将long数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(long value) { return BitConverter.GetBytes(value); @@ -79,8 +88,8 @@ namespace Modbus.Net /// /// 将ushort数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(ushort value) { return BitConverter.GetBytes(value); @@ -89,8 +98,8 @@ namespace Modbus.Net /// /// 将uint数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(uint value) { return BitConverter.GetBytes(value); @@ -99,8 +108,8 @@ namespace Modbus.Net /// /// 将ulong数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(ulong value) { return BitConverter.GetBytes(value); @@ -109,8 +118,8 @@ namespace Modbus.Net /// /// 将float数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(float value) { return BitConverter.GetBytes(value); @@ -119,8 +128,8 @@ namespace Modbus.Net /// /// 将double数字转换为byte数组 /// - /// - /// + /// 待转换的值 + /// 转换后的byte数组 public virtual byte[] GetBytes(double value) { return BitConverter.GetBytes(value); @@ -129,9 +138,9 @@ namespace Modbus.Net /// /// 将object数字转换为byte数组 /// - /// - /// - /// + /// 待转换的值 + /// 待转换的值的类型 + /// 转换后的byte数组 public virtual byte[] GetBytes(object value, Type type) { switch (type.FullName) @@ -191,11 +200,11 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为对应类型的数字 /// - /// - /// - /// - /// - /// + /// 待转换的字节数组 + /// 转换数字的位置 + /// 转换数字的比特位置(仅Type为bool的时候有效) + /// 转换的类型 + /// 转换出的数字 public virtual object GetValue(byte[] data, ref int pos, ref int subPos, Type t) { switch (t.FullName) @@ -260,9 +269,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为byte数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual byte GetByte(byte[] data, ref int pos) { var t = data[pos]; @@ -273,9 +282,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为short数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual short GetShort(byte[] data, ref int pos) { var t = BitConverter.ToInt16(data, pos); @@ -286,9 +295,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为int数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual int GetInt(byte[] data, ref int pos) { var t = BitConverter.ToInt32(data, pos); @@ -299,9 +308,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为long数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual long GetLong(byte[] data, ref int pos) { var t = BitConverter.ToInt64(data, pos); @@ -312,9 +321,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为ushort数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual ushort GetUShort(byte[] data, ref int pos) { var t = BitConverter.ToUInt16(data, pos); @@ -325,9 +334,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为uint数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual uint GetUInt(byte[] data, ref int pos) { var t = BitConverter.ToUInt32(data, pos); @@ -338,9 +347,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为ulong数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual ulong GetULong(byte[] data, ref int pos) { var t = BitConverter.ToUInt64(data, pos); @@ -351,9 +360,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为float数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual float GetFloat(byte[] data, ref int pos) { var t = BitConverter.ToSingle(data, pos); @@ -364,9 +373,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为double数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public virtual double GetDouble(byte[] data, ref int pos) { var t = BitConverter.ToDouble(data, pos); @@ -377,11 +386,11 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为字符串 /// - /// - /// - /// - /// - /// + /// 待转换的数组 + /// 转换的个数 + /// 转换数字的位置 + /// 编码方法 + /// 转换出的字符串 public virtual string GetString(byte[] data, int count, ref int pos, Encoding encoding) { var t = encoding.GetString(data, pos, count); @@ -392,9 +401,9 @@ namespace Modbus.Net /// /// 将byte数组中相应的位置转换为8个bit数字 /// - /// - /// - /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的位数组 public virtual bool[] GetBits(byte[] data, ref int pos) { var t = new bool[8]; @@ -438,10 +447,10 @@ namespace Modbus.Net /// /// 获取一个字节数组中某个Bit位的数据 /// - /// - /// - /// - /// + /// byte数字 + /// bit数组中的对应位置 + /// 小数位 + /// 对应位置的bit元素 public virtual bool GetBit(byte[] number, ref int pos, ref int subPos) { return GetBit(number[pos], ref pos, ref subPos); @@ -450,8 +459,8 @@ namespace Modbus.Net /// /// 反转一个字节的8个Bit位 /// - /// - /// + /// 原始bit数组 + /// 反转的bit数组 public virtual byte ReverseByte(byte originalByte) { byte result = 0; @@ -467,8 +476,8 @@ namespace Modbus.Net /// /// 将待转换的对象数组转换为需要发送的byte数组 /// - /// - /// + /// object数组 + /// byte数组 public virtual byte[] ObjectArrayToByteArray(object[] contents) { var b = false; @@ -606,10 +615,10 @@ namespace Modbus.Net /// /// 将一个byte数组转换成用户指定类型的数组,使用模板参数确定需要转换的类型 /// - /// - /// - /// - /// + /// 目标数组类型 + /// 待转换的数组 + /// 转换的个数 + /// 以T为类型的数组 public virtual T[] ByteArrayToDestinationArray(byte[] contents, int getCount) { var objectArray = _Instance.ByteArrayToObjectArray(contents, @@ -733,6 +742,14 @@ namespace Modbus.Net return array; } + /// + /// 在一个数组中写一个值 + /// + /// 待写入的字节数组 + /// 设置的位置 + /// 设置的比特位位置(仅setValue为bit的时候有效) + /// 写入的值 + /// 写入是否成功 public bool SetValue(byte[] contents, int setPos, int subPos, object setValue) { var type = setValue.GetType(); @@ -802,7 +819,7 @@ namespace Modbus.Net /// 待设置的byte数组 /// 设置的位置 /// 要设置的值 - /// + /// 设置是否成功 public virtual bool SetValue(byte[] contents, int pos, object setValue) { try @@ -823,7 +840,7 @@ namespace Modbus.Net /// byte数子 /// 设置位置 /// 设置bit大小,true为1,false为0 - /// + /// 设置是否成功 protected byte SetBit(byte number, int subPos, bool setBit) { var creation = 0; @@ -851,7 +868,7 @@ namespace Modbus.Net /// 位置 /// bit位置 /// bit数 - /// + /// 设置是否成功 public virtual bool SetBit(byte[] contents, int pos, int subPos, bool setValue) { try @@ -869,6 +886,9 @@ namespace Modbus.Net private static ValueHelper _instance; + /// + /// 实例,继承时请把它覆写掉 + /// protected virtual ValueHelper _Instance => _instance; /// @@ -876,6 +896,11 @@ namespace Modbus.Net /// public static ValueHelper Instance => _instance ?? (_instance = new ValueHelper()); + /// + /// 根据端格式获取ValueHelper实例 + /// + /// 端格式 + /// 对应的ValueHelper实例 public static ValueHelper GetInstance(Endian endian) { switch (endian) @@ -902,61 +927,123 @@ namespace Modbus.Net #endregion } + /// + /// 值与字节数组之间转换的辅助类(大端格式),这是一个Singleton类 + /// public class BigEndianValueHelper : ValueHelper { private static BigEndianValueHelper _bigEndianInstance; + /// + /// 构造器 + /// protected BigEndianValueHelper() { } + /// + /// 覆写的实例获取 + /// protected override ValueHelper _Instance => _bigEndianInstance; + /// + /// 是否为大端 + /// protected new bool LittleEndian => false; + /// + /// 覆盖的获取实例的方法 + /// public new static BigEndianValueHelper Instance => _bigEndianInstance ?? (_bigEndianInstance = new BigEndianValueHelper()); + /// + /// 将short数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(short value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将int数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(int value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将long数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 + /// 转换出的数字 public override byte[] GetBytes(long value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将ushort数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(ushort value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将uint数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(uint value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将ulong数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(ulong value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将float数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(float value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将double数字转换为byte数组 + /// + /// 待转换的值 + /// 转换后的byte数组 public override byte[] GetBytes(double value) { return Reverse(BitConverter.GetBytes(value)); } + /// + /// 将byte数组中相应的位置转换为short数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override short GetShort(byte[] data, ref int pos) { Array.Reverse(data, pos, 2); @@ -966,6 +1053,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为int数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override int GetInt(byte[] data, ref int pos) { Array.Reverse(data, pos, 4); @@ -975,6 +1068,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为long数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override long GetLong(byte[] data, ref int pos) { Array.Reverse(data, pos, 8); @@ -984,6 +1083,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为ushort数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override ushort GetUShort(byte[] data, ref int pos) { Array.Reverse(data, pos, 2); @@ -993,6 +1098,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为uint数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override uint GetUInt(byte[] data, ref int pos) { Array.Reverse(data, pos, 4); @@ -1002,6 +1113,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为ulong数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override ulong GetULong(byte[] data, ref int pos) { Array.Reverse(data, pos, 8); @@ -1011,6 +1128,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为float数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override float GetFloat(byte[] data, ref int pos) { Array.Reverse(data, pos, 4); @@ -1020,6 +1143,12 @@ namespace Modbus.Net return t; } + /// + /// 将byte数组中相应的位置转换为double数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的数字 public override double GetDouble(byte[] data, ref int pos) { Array.Reverse(data, pos, 8); @@ -1029,6 +1158,11 @@ namespace Modbus.Net return t; } + /// + /// 反转一个byte数组 + /// + /// 待反转的数组 + /// 反转后的数组 private byte[] Reverse(byte[] data) { Array.Reverse(data); @@ -1036,23 +1170,48 @@ namespace Modbus.Net } } + /// + /// 值与字节数组之间转换的辅助类(大端-大端位格式),这是一个Singleton类 + /// public class BigEndianMsbValueHelper : BigEndianValueHelper { private static BigEndianValueHelper _bigEndianInstance; + /// + /// 构造函数 + /// protected BigEndianMsbValueHelper() { } + /// + /// 覆写的实例获取方法 + /// protected override ValueHelper _Instance => _bigEndianInstance; + /// + /// 是否为小端 + /// protected new bool LittleEndian => false; + /// + /// 是否为小端位 + /// protected new bool LittleEndianBit => false; + /// + /// 覆盖的实例获取方法 + /// public new static BigEndianValueHelper Instance => _bigEndianInstance ?? (_bigEndianInstance = new BigEndianMsbValueHelper()); + /// + /// 获取一个byte中相对应的bit数组展开中第n个位置中的bit元素。 + /// + /// byte数字 + /// bit数组中的对应位置 + /// 小数位 + /// 对应位置的bit元素 public override bool GetBit(byte[] number, ref int pos, ref int subPos) { if (subPos < 0 && subPos > 7) throw new IndexOutOfRangeException(); @@ -1068,6 +1227,12 @@ namespace Modbus.Net return bit; } + /// + /// 将byte数组中相应的位置转换为8个bit数字 + /// + /// 待转换的数组 + /// 转换数字的位置 + /// 转换出的位数组 public override bool[] GetBits(byte[] data, ref int pos) { var t = base.GetBits(data, ref pos); @@ -1075,6 +1240,13 @@ namespace Modbus.Net return t; } + /// + /// 设置对应数字中相应位置的bit的值 + /// + /// byte数子 + /// 设置位置 + /// 设置bit大小,true为1,false为0 + /// 设置是否成功 public override bool SetBit(byte[] number, int pos, int subPos, bool setBit) { return base.SetBit(number, pos, 7 - subPos, setBit); diff --git a/Tests/Modbus.Net.Tests/MachineMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs index e6d980a..29dcea8 100644 --- a/Tests/Modbus.Net.Tests/MachineMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -15,7 +15,7 @@ namespace Modbus.Net.Tests public void GetUtility() { BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); - var utility = baseMachine.GetUtility(); + var utility = baseMachine.GetUtility(); var methods = utility.GetType().GetRuntimeMethods(); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetTimeAsync") != null, true); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetTimeAsync") != null, true); @@ -25,9 +25,9 @@ namespace Modbus.Net.Tests public async Task InvokeUtility() { BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); - var success = await baseMachine.BaseUtility.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); + var success = await baseMachine.BaseUtility.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); Assert.AreEqual(success, true); - var time = await baseMachine.BaseUtility.InvokeUtilityMethod>("GetTimeAsync"); + var time = await baseMachine.BaseUtility.InvokeUtilityMethod>("GetTimeAsync"); Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true); } @@ -46,7 +46,7 @@ namespace Modbus.Net.Tests DataType = typeof(bool) } }, true, 2, 0); - var success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", + var success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", MachineSetDataType.Address, new Dictionary { @@ -55,9 +55,9 @@ namespace Modbus.Net.Tests } }); Assert.AreEqual(success, true); - var datas = await baseMachine.InvokeMachineMethod>>("GetDatasAsync", MachineGetDataType.Address); + var datas = await baseMachine.InvokeMachineMethod>>("GetDatasAsync", MachineGetDataType.Address); Assert.AreEqual(datas["0X 1.0"].PlcValue, 1); - success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", + success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", MachineSetDataType.Address, new Dictionary { From 139b093a4f5bf1dac246f90d653b0665214833df Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 11 May 2017 10:49:31 +0800 Subject: [PATCH 09/62] 2017-05-11 update 1 move setting files to App.config --- Modbus.Net/Modbus.Net.Core/App.config | 13 ++ .../Modbus.Net.Core/ConfigurationManager.cs | 18 +++ .../Modbus.Net.Core/Modbus.Net.Core.csproj | 18 +-- .../Modbus.Net.Modbus.csproj | 4 + .../Modbus.Net.Modbus/ModbusAsciiProtocal.cs | 6 +- .../Modbus.Net.Modbus/ModbusRtuProtocal.cs | 6 +- .../Modbus.Net.Modbus/ModbusTcpProtocal.cs | 6 +- .../ModbusTcpProtocalLinker.cs | 6 +- .../Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs | 3 +- .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 8 +- .../Modbus.Net.OPC/OpcDaProtocalLinker.cs | 5 +- .../Modbus.Net.OPC/OpcUaProtocalLinker.cs | 3 +- .../Modbus.Net.Siemens.csproj | 6 + .../Modbus.Net.Siemens/SiemensPpiProtocal.cs | 5 +- .../Modbus.Net.Siemens/SiemensTcpProtocal.cs | 5 +- .../SiemensTcpProtocalLinker.cs | 3 +- Modbus.Net/Modbus.Net/App.config | 14 ++ Modbus.Net/Modbus.Net/ComProtocalLinker.cs | 7 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 15 +- .../ConfigurationManager.Designer.cs | 137 ----------------- .../src/Base.Common/ConfigurationManager.resx | 144 ------------------ .../src/Base.Common/TcpProtocalLinker.cs | 10 +- 22 files changed, 110 insertions(+), 332 deletions(-) create mode 100644 Modbus.Net/Modbus.Net.Core/App.config create mode 100644 Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs create mode 100644 Modbus.Net/Modbus.Net/App.config delete mode 100644 Modbus.Net/src/Base.Common/ConfigurationManager.Designer.cs delete mode 100644 Modbus.Net/src/Base.Common/ConfigurationManager.resx diff --git a/Modbus.Net/Modbus.Net.Core/App.config b/Modbus.Net/Modbus.Net.Core/App.config new file mode 100644 index 0000000..e85257a --- /dev/null +++ b/Modbus.Net/Modbus.Net.Core/App.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs new file mode 100644 index 0000000..55e5301 --- /dev/null +++ b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.IO; +using Microsoft.Extensions.Configuration; + +namespace Modbus.Net +{ + public static class ConfigurationManager + { + private static IConfigurationBuilder builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .AddXmlFile("App.config"); + + private static IConfigurationRoot Configuration => builder.Build(); + + public static IConfigurationSection AppSettings => Configuration.GetSection("AppSettings"); + } +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 911a4ef..3e7c4ae 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -51,23 +51,11 @@ + + + - - - True - True - ConfigurationManager.resx - - - - - - ResXFileCodeGenerator - ConfigurationManager.Designer.cs - - - \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index 76b0b4f..d0c29f2 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -27,4 +27,8 @@ + + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs index 0928bdf..f75400c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs @@ -1,4 +1,6 @@ -namespace Modbus.Net.Modbus +using System.Configuration; + +namespace Modbus.Net.Modbus { /// /// Modbus/Ascii码协议 @@ -6,7 +8,7 @@ public class ModbusAsciiProtocal : ModbusProtocal { public ModbusAsciiProtocal(byte slaveAddress, byte masterAddress, Endian endian) - : this(ConfigurationManager.COM, slaveAddress, masterAddress, endian) + : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, endian) { } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs index 9fbe229..53fab41 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs @@ -1,4 +1,6 @@ -namespace Modbus.Net.Modbus +using System.Configuration; + +namespace Modbus.Net.Modbus { /// /// Modbus/Rtu协议 @@ -6,7 +8,7 @@ public class ModbusRtuProtocal : ModbusProtocal { public ModbusRtuProtocal(byte slaveAddress, byte masterAddress, Endian endian) - : this(ConfigurationManager.COM, slaveAddress, masterAddress, endian) + : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, endian) { } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs index ff8631c..d403e21 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs @@ -1,4 +1,6 @@ -namespace Modbus.Net.Modbus +using System.Configuration; + +namespace Modbus.Net.Modbus { /// /// Modbus/Tcp协议 @@ -6,7 +8,7 @@ public class ModbusTcpProtocal : ModbusProtocal { public ModbusTcpProtocal(byte slaveAddress, byte masterAddress, Endian endian) - : this(ConfigurationManager.IP, slaveAddress, masterAddress, endian) + : this(ConfigurationManager.AppSettings["IP"], slaveAddress, masterAddress, endian) { } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs index 229bd68..f49667c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs @@ -1,11 +1,13 @@ -namespace Modbus.Net.Modbus +using System.Configuration; + +namespace Modbus.Net.Modbus { /// /// Modbus/Tcp协议连接器 /// public class ModbusTcpProtocalLinker : TcpProtocalLinker { - public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.ModbusPort)) + public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"])) { } diff --git a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs index 802097b..991f80c 100644 --- a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs +++ b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -13,7 +14,7 @@ namespace Modbus.Net.OPC.FBox public string LinkerName { get; set; } public FBoxOpcDaMachine(string localSequence, string linkerName, - IEnumerable getAddresses, bool keepConnect) : base(ConfigurationManager.FBoxOpcDaHost, getAddresses, keepConnect) + IEnumerable getAddresses, bool keepConnect) : base(ConfigurationManager.AppSettings["FBoxOpcDaHost"], getAddresses, keepConnect) { LocalSequence = localSequence; LinkerName = linkerName; diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index e208dc5..3f38142 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -24,11 +24,17 @@ - + + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Configuration.dll + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs index 2307645..f65da98 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Configuration; +using System.Text; namespace Modbus.Net.OPC { @@ -7,7 +8,7 @@ namespace Modbus.Net.OPC /// public class OpcDaProtocalLinker : OpcProtocalLinker { - public OpcDaProtocalLinker() : this(ConfigurationManager.OpcDaHost) + public OpcDaProtocalLinker() : this(ConfigurationManager.AppSettings["OpcDaHost"]) { } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs index dd090e5..8048b97 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -11,7 +12,7 @@ namespace Modbus.Net.OPC /// public class OpcUaProtocalLinker : OpcProtocalLinker { - public OpcUaProtocalLinker() : this(ConfigurationManager.OpcUaHost) + public OpcUaProtocalLinker() : this(ConfigurationManager.AppSettings["OpcUaHost"]) { } diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 197f12f..3c27504 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -25,5 +25,11 @@ + + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Configuration.dll + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs index 1b71c31..1585154 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Configuration; +using System.Threading.Tasks; namespace Modbus.Net.Siemens { @@ -10,7 +11,7 @@ namespace Modbus.Net.Siemens private readonly string _com; public SiemensPpiProtocal(byte slaveAddress, byte masterAddress) - : this(ConfigurationManager.COM, slaveAddress, masterAddress) + : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress) { } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs index f49751e..cc44acd 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Configuration; +using System.Threading.Tasks; namespace Modbus.Net.Siemens { @@ -18,7 +19,7 @@ namespace Modbus.Net.Siemens 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) + ushort maxPdu) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.AppSettings["IP"]) { } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs index 88c65b0..23f4b62 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs @@ -1,4 +1,5 @@ using System; +using System.Configuration; namespace Modbus.Net.Siemens { @@ -8,7 +9,7 @@ namespace Modbus.Net.Siemens public class SiemensTcpProtocalLinker : TcpProtocalLinker { public SiemensTcpProtocalLinker(string ip) - : base(ip, int.Parse(ConfigurationManager.SiemensPort)) + : base(ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"])) { } diff --git a/Modbus.Net/Modbus.Net/App.config b/Modbus.Net/Modbus.Net/App.config new file mode 100644 index 0000000..46b488f --- /dev/null +++ b/Modbus.Net/Modbus.Net/App.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs index 8ddcfc6..95e61a5 100644 --- a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs @@ -1,4 +1,5 @@ -using System.IO.Ports; +using System.Configuration; +using System.IO.Ports; namespace Modbus.Net { @@ -15,7 +16,7 @@ namespace Modbus.Net /// 停止位 /// 数据位 protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits) - : this(ConfigurationManager.COM, baudRate, parity, stopBits, dataBits) + : this(ConfigurationManager.AppSettings["COM"], baudRate, parity, stopBits, dataBits) { } @@ -30,7 +31,7 @@ namespace Modbus.Net protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits) { //初始化连对象 - BaseConnector = new ComConnector(com, baudRate, parity, stopBits, dataBits, 30000); + BaseConnector = new ComConnector(com, baudRate, parity, stopBits, dataBits, int.Parse(ConfigurationManager.AppSettings["ComConnectionTimeout"])); } } } \ 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 5487e41..2d503be 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -50,18 +50,9 @@ - - True - True - ConfigurationManager.resx - - - - - - ResXFileCodeGenerator - ConfigurationManager.Designer.cs - + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Configuration.dll + \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/ConfigurationManager.Designer.cs b/Modbus.Net/src/Base.Common/ConfigurationManager.Designer.cs deleted file mode 100644 index f261ccf..0000000 --- a/Modbus.Net/src/Base.Common/ConfigurationManager.Designer.cs +++ /dev/null @@ -1,137 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 -// -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 -// -//------------------------------------------------------------------------------ - -using System.Reflection; - -namespace Modbus.Net { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class ConfigurationManager { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ConfigurationManager() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Modbus.Net.ConfigurationManager", typeof(ConfigurationManager).GetTypeInfo().Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 使用此强类型资源类,为所有资源查找 - /// 重写当前线程的 CurrentUICulture 属性。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 查找类似 COM1 的本地化字符串。 - /// - public static string COM { - get { - return ResourceManager.GetString("COM", resourceCulture); - } - } - - /// - /// 查找类似 opcda://localhost/FBoxOpcServer 的本地化字符串。 - /// - public static string FBoxOpcDaHost { - get { - return ResourceManager.GetString("FBoxOpcDaHost", resourceCulture); - } - } - - /// - /// 查找类似 192.168.1.1 的本地化字符串。 - /// - public static string IP { - get { - return ResourceManager.GetString("IP", resourceCulture); - } - } - - /// - /// 查找类似 5000 的本地化字符串。 - /// - public static string IPConnectionTimeout { - get { - return ResourceManager.GetString("IPConnectionTimeout", resourceCulture); - } - } - - /// - /// 查找类似 502 的本地化字符串。 - /// - public static string ModbusPort { - get { - return ResourceManager.GetString("ModbusPort", resourceCulture); - } - } - - /// - /// 查找类似 opcda://localhost/... 的本地化字符串。 - /// - public static string OpcDaHost { - get { - return ResourceManager.GetString("OpcDaHost", resourceCulture); - } - } - - /// - /// 查找类似 opc.tcp://localhost/... 的本地化字符串。 - /// - public static string OpcUaHost { - get { - return ResourceManager.GetString("OpcUaHost", resourceCulture); - } - } - - /// - /// 查找类似 102 的本地化字符串。 - /// - public static string SiemensPort { - get { - return ResourceManager.GetString("SiemensPort", resourceCulture); - } - } - } -} diff --git a/Modbus.Net/src/Base.Common/ConfigurationManager.resx b/Modbus.Net/src/Base.Common/ConfigurationManager.resx deleted file mode 100644 index 192a30e..0000000 --- a/Modbus.Net/src/Base.Common/ConfigurationManager.resx +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - COM1 - - - opcda://localhost/FBoxOpcServer - - - 192.168.1.1 - - - 5000 - - - 502 - - - opcda://localhost/... - - - opc.tcp://localhost/... - - - 102 - - \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs index cb1077a..92cb4b0 100644 --- a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs @@ -1,4 +1,8 @@ -namespace Modbus.Net +#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47 +using System.Configuration; +#endif + +namespace Modbus.Net { /// /// Tcp连接对象 @@ -8,7 +12,7 @@ /// /// 构造器 /// - protected TcpProtocalLinker() : this(ConfigurationManager.IP, int.Parse(ConfigurationManager.ModbusPort)) + protected TcpProtocalLinker() : this(ConfigurationManager.AppSettings["IP"], int.Parse(ConfigurationManager.AppSettings["ModbusPort"])) { } @@ -20,7 +24,7 @@ protected TcpProtocalLinker(string ip, int port) { //初始化连接对象 - BaseConnector = new TcpConnector(ip, port, int.Parse(ConfigurationManager.IPConnectionTimeout)); + BaseConnector = new TcpConnector(ip, port, int.Parse(ConfigurationManager.AppSettings["IPConnectionTimeout"])); } } } \ No newline at end of file From 16f63d079e7fafbd08b9353582a12e4035d38293 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Mon, 15 May 2017 14:07:32 +0800 Subject: [PATCH 10/62] 2017-05-15 Update 1 TaskManager Remake. Bug Fix.(Not Test) --- .../Modbus.Net.Core/ConfigurationManager.cs | 2 + .../Modbus.Net.Core/Modbus.Net.Core.csproj | 2 + Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 2 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 5 + Modbus.Net/src/Base.Common/BaseMachine.cs | 42 +- Modbus.Net/src/Base.Common/BaseProtocal.cs | 5 - Modbus.Net/src/Base.Common/BaseUtility.cs | 16 +- Modbus.Net/src/Base.Common/ProtocalLinker.cs | 5 - Modbus.Net/src/Base.Common/TaskManager.cs | 796 ++++++++++-------- Modbus.Net/src/Base.Common/TypeExtensions.cs | 126 +++ Samples/AnyType/Controllers/HomeController.cs | 33 +- .../TaskManager/Controllers/HomeController.cs | 33 +- Tests/Modbus.Net.Tests/BaseTest.cs | 2 +- 13 files changed, 621 insertions(+), 448 deletions(-) create mode 100644 Modbus.Net/src/Base.Common/TypeExtensions.cs diff --git a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs index 55e5301..9fb6291 100644 --- a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs +++ b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs @@ -14,5 +14,7 @@ namespace Modbus.Net private static IConfigurationRoot Configuration => builder.Build(); public static IConfigurationSection AppSettings => Configuration.GetSection("AppSettings"); + + public static IConfigurationSection ConnectionStrings => Configuration.GetSection("ConnectionStrings"); } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 3e7c4ae..c1c1818 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -48,12 +48,14 @@ + + diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index 137637b..50ce8a5 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Modbus.Net.OPC { - public abstract class OpcUtility : BaseUtility + public abstract class OpcUtility : BaseUtility> { protected OpcUtility(string connectionString) : base(0, 0) { diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index 2d503be..00e6daa 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -47,6 +47,11 @@ + + + + + diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 80d26c8..757df30 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -661,6 +661,11 @@ namespace Modbus.Net { return BaseUtility.Disconnect(); } + + public string GetMachineIdString() + { + return Id.ToString(); + } } internal class BaseMachineEqualityComparer : IEqualityComparer> @@ -754,7 +759,7 @@ namespace Modbus.Net /// /// 地址单元 /// - public class AddressUnit where TKey : IEquatable + public class AddressUnit : IEquatable> where TKey : IEquatable { /// /// 数据单元Id @@ -815,31 +820,15 @@ namespace Modbus.Net /// 扩展 /// public UnitExtend UnitExtend { get; set; } - } - internal struct AddressUnitEqualityComparer : IEqualityComparer> where TKey : IEquatable - { - public bool Equals(AddressUnit x, AddressUnit y) + public bool Equals(AddressUnit other) { - return (x.Area.ToUpper() == y.Area.ToUpper() && x.Address == y.Address) || x.Id.Equals(y.Id); - } - - public int GetHashCode(AddressUnit obj) - { - return obj.GetHashCode(); + return (Area.ToUpper() == other.Area.ToUpper() && Address == other.Address) || Id.Equals(other.Id); } } - /// - /// 设备的抽象 - /// - public interface IMachineProperty where TKey : IEquatable + public interface IMachinePropertyWithoutKey { - /// - /// Id - /// - TKey Id { get; set; } - /// /// 工程名 /// @@ -898,5 +887,18 @@ namespace Modbus.Net /// /// 是否断开成功 bool Disconnect(); + + string GetMachineIdString(); + } + + /// + /// 设备的抽象 + /// + public interface IMachineProperty : IMachinePropertyWithoutKey where TKey : IEquatable + { + /// + /// Id + /// + TKey Id { get; set; } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index c4db1f3..627be11 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -10,11 +10,6 @@ namespace Modbus.Net /// public abstract class BaseProtocal : BaseProtocal { - /// - /// 协议的连接器 - /// - public new ProtocalLinker ProtocalLinker { get; set; } - /// /// 构造器 /// diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index 830b401..86172fb 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -28,7 +28,7 @@ namespace Modbus.Net /// /// 基础Api入口 /// - public abstract class BaseUtility : BaseUtility + public abstract class BaseUtility : BaseUtility { /// /// 构造器 @@ -37,23 +37,17 @@ namespace Modbus.Net { } - - /// - /// 协议收发主体 - /// - protected new BaseProtocal Wrapper; - } /// /// 基础Api入口 /// - public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData + public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData where TProtocalUnit : ProtocalUnit { /// /// 协议收发主体 /// - protected BaseProtocal> Wrapper; + protected BaseProtocal Wrapper; /// /// 构造器 @@ -160,7 +154,7 @@ namespace Modbus.Net return null; } } - + /// /// 获取数据 /// @@ -296,7 +290,7 @@ namespace Modbus.Net if (this is TUtilityMethod) { Type t = typeof(TUtilityMethod); - object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) + object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray(), false) .Invoke(this, parameters); return (TReturnType)returnValue; } diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index 0d2bf45..3ec9995 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -9,11 +9,6 @@ namespace Modbus.Net /// public abstract class ProtocalLinker : ProtocalLinker { - /// - /// 传输连接器 - /// - protected new BaseConnector BaseConnector; - /// /// 发送并接收数据 /// diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index f6058ec..00ae740 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -8,34 +8,27 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Nito.AsyncEx; namespace Modbus.Net { /// /// 返回结果的定义类 /// - public class TaskReturnDef : TaskReturnDef + public class DataReturnDef : DataReturnDef { - + } /// /// 返回结果的定义类 /// - public class TaskReturnDef where TMachineKey : IEquatable + public class DataReturnDef where TMachineKey : IEquatable { public TMachineKey MachineId { get; set; } public Dictionary ReturnValues { get; set; } } - /// - /// 时间定义 - /// - public static class TimeRestore - { - public static int Restore = 0; - } - public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler { /// @@ -105,7 +98,7 @@ namespace Modbus.Net /// private void NotifyThreadPoolOfPendingWork() { -#if NET40 || NET45 || NET451 || NET452 || NET46 || NET461 || NET462 +#if NET40 || NET45 || NET451 || NET452 || NET46 || NET461 || NET462 || NET47 ThreadPool.UnsafeQueueUserWorkItem(_ => #else ThreadPool.QueueUserWorkItem(_ => @@ -199,51 +192,270 @@ namespace Modbus.Net } } + public class TaskMachine where TMachineKey : IEquatable + { + private TaskFactory _tasks { get; } + + public TaskMachine(IMachineProperty machine, TaskFactory taskFactory) + { + Machine = machine; + _tasks = taskFactory; + } + + public IMachineProperty Machine { get; } + + public List TasksWithTimer { get; set; } + + public bool InvokeTimer(TaskItem task) + { + task.DetectConnected = () => Machine.IsConnected; + task.GetMachine = () => Machine; + task.GetTaskFactory = () => _tasks; + + if (!TasksWithTimer.Exists(taskCon => taskCon.Name == task.Name)) + { + TasksWithTimer.Add(task); + task.StartTimer(); + return true; + } + return false; + } + + public bool StopTimer(string taskItemName) + { + if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName)) + { + var task = TasksWithTimer.FirstOrDefault(taskCon => taskCon.Name == taskItemName); + task?.StopTimer(); + TasksWithTimer.Remove(task); + return true; + } + return false; + } + + public bool StopAllTimers() + { + bool ans = true; + foreach (var task in TasksWithTimer) + { + ans = ans && StopTimer(task.Name); + } + return ans; + } + + public bool PauseTimer(string taskItemName) + { + if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName)) + { + var task = TasksWithTimer.FirstOrDefault(taskCon => taskCon.Name == taskItemName); + task?.StopTimer(); + return true; + } + return false; + } + + public bool PauseAllTimers() + { + bool ans = true; + foreach (var task in TasksWithTimer) + { + ans = ans && PauseTimer(task.Name); + } + return ans; + } + + public bool ContinueTimer(string taskItemName) + { + if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName)) + { + var task = TasksWithTimer.FirstOrDefault(taskCon => taskCon.Name == taskItemName); + task?.StartTimer(); + return true; + } + return false; + } + + public bool ContinueAllTimers() + { + bool ans = true; + foreach (var task in TasksWithTimer) + { + ans = ans && ContinueTimer(task.Name); + } + return ans; + } + + public async Task InvokeOnce(TaskItem task) + { + if (Machine.IsConnected) + { + var ans = await task.Invoke(Machine, _tasks, task.Params); + task.Return(ans); + return true; + } + return false; + } + } + + internal class TaskMachineEqualityComparer : IEqualityComparer> + where TKey : IEquatable + { + public bool Equals(TaskMachine x, TaskMachine y) + { + return x.Machine.Id.Equals(y.Machine.Id); + } + + public int GetHashCode(TaskMachine obj) + { + return obj.GetHashCode(); + } + } + + public interface ITaskItem + { + string Name { get; set; } + + bool StartTimer(); + + bool StopTimer(); + } + + public class TaskItemGetData : TaskItem + { + public TaskItemGetData(Action returnFunc, int getCycle, int sleepCycle) + { + Name = "GetDatas"; + Invoke = async (machine, tasks, parameters) => + { + var cts = new CancellationTokenSource(); + cts.CancelAfter(TimeSpan.FromSeconds(100000)); + var ans = + await tasks.Run( + async () => await machine.InvokeMachineMethod>>("GetDatasAsync", + MachineGetDataType.CommunicationTag).WithCancellation(cts.Token)); + return new DataReturnDef + { + MachineId = machine.GetMachineIdString(), + ReturnValues = ans, + }; + }; + Params = null; + Return = returnFunc; + TimerDisconnectedTime = sleepCycle; + TimerTime = getCycle; + } + } + + public class TaskItemSetData : TaskItem + { + public TaskItemSetData(Dictionary values) + { + Name = "SetDatas"; + Invoke = Invoke = async (machine, tasks, parameters) => + { + var cts = new CancellationTokenSource(); + cts.CancelAfter(TimeSpan.FromSeconds(100000)); + var ans = + await tasks.Run( + async () => await machine.InvokeMachineMethod>("SetDatasAsync", parameters[0], + MachineSetDataType.CommunicationTag).WithCancellation(cts.Token)); + return ans; + }; + Params = new object[]{values}; + } + } + + public class TaskItem : ITaskItem, IEquatable> + { + public string Name { get; set; } + private Timer Timer { get; set; } + public int TimerTime { get; set; } + private Timer TimerDisconnected { get; set; } + public int TimerDisconnectedTime { get; set; } + public Func> Invoke { get; set; } + internal Func DetectConnected { get; set; } + public object[] Params { get; set; } + public Action Return { get; set; } + internal Func GetMachine { get; set; } + internal Func GetTaskFactory { get; set; } + + public bool Equals(TaskItem other) + { + return Name == other?.Name; + } + + public bool StartTimer() + { + ActivateTimerDisconnected(); + return true; + } + + private void ActivateTimer() + { + Timer = new Timer(async state => + { + if (!DetectConnected()) TimerChangeToDisconnect(); + var ans = await Invoke(GetMachine(),GetTaskFactory(),Params); + Return(ans); + }, null, 0, TimerTime); + } + + private void DeactivateTimer() + { + Timer.Dispose(); + Timer = null; + } + + private void ActivateTimerDisconnected() + { + TimerDisconnected = new Timer(async state => + { + await GetMachine().ConnectAsync(); + if (DetectConnected()) TimerChangeToConnect(); + }, null, 0, TimerDisconnectedTime); + } + + private void DeactivateTimerDisconnected() + { + TimerDisconnected.Dispose(); + TimerDisconnected = null; + } + + private bool TimerChangeToConnect() + { + DeactivateTimerDisconnected(); + ActivateTimer(); + return true; + } + + private bool TimerChangeToDisconnect() + { + DeactivateTimer(); + ActivateTimerDisconnected(); + return true; + } + + public bool StopTimer() + { + DeactivateTimer(); + DeactivateTimerDisconnected(); + return true; + } + } + /// /// 任务调度器 /// public class TaskManager : TaskManager { - public TaskManager(int maxRunningTask, int getCycle, bool keepConnect, + public TaskManager(int maxRunningTask, bool keepConnect, MachineDataType dataType = MachineDataType.CommunicationTag) - : base(maxRunningTask, getCycle, keepConnect, dataType) + : base(maxRunningTask, keepConnect, dataType) { } - public new delegate void ReturnValuesDelegate(TaskReturnDef returnValue); - - public new event ReturnValuesDelegate ReturnValues; - - /// - /// 执行对具体设备的数据更新 - /// - /// 设备的实例 - /// - protected override async Task RunTask(IMachineProperty machine) - { - try - { - var ans = await GetValue(machine); - ReturnValues?.Invoke(new TaskReturnDef - { - MachineId = machine.Id, - ReturnValues = ans - }); - } - catch (Exception e) - { - if (!machine.IsConnected) - { - MoveMachineToUnlinked(machine.Id); - } - ReturnValues?.Invoke(new TaskReturnDef - { - MachineId = machine.Id, - ReturnValues = null - }); - } - } - public void AddMachine(BaseMachine machine) { base.AddMachine(machine); @@ -271,29 +483,13 @@ namespace Modbus.Net /// public class TaskManager where TMachineKey : IEquatable { - /// - /// 返回数据代理 - /// - /// - public delegate void ReturnValuesDelegate(TaskReturnDef returnValue); - /// /// 正在运行的设备 /// - private readonly HashSet> _machines; - - /// - /// 不在运行的设备 - /// - private readonly HashSet> _unlinkedMachines; + private readonly HashSet> _machines; private CancellationTokenSource _cts; - /// - /// 获取间隔 - /// - private int _getCycle; - /// /// 保持连接 /// @@ -309,34 +505,32 @@ namespace Modbus.Net /// private TaskFactory _tasks; - /// - /// 正常读取的计时器 - /// - private Timer _timer; - - /// - /// 重连计时器 - /// - private Timer _timer2; - /// /// 构造一个TaskManager /// /// 同时可以运行的任务数 - /// 读取数据的时间间隔(毫秒) /// 读取数据后是否保持连接 /// 获取与设置数据的方式 - public TaskManager(int maxRunningTask, int getCycle, bool keepConnect, + public TaskManager(int maxRunningTask, bool keepConnect, MachineDataType dataType = MachineDataType.CommunicationTag) { _scheduler = new LimitedConcurrencyLevelTaskScheduler(maxRunningTask); _machines = - new HashSet>(new BaseMachineEqualityComparer()); - _unlinkedMachines = - new HashSet>(new BaseMachineEqualityComparer()); - _getCycle = getCycle; + new HashSet>(new TaskMachineEqualityComparer()); KeepConnect = keepConnect; MachineDataType = dataType; + _cts = new CancellationTokenSource(); + _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); + } + + /// + /// 强制停止所有正在运行的任务 + /// + public void TaskHalt() + { + _cts.Cancel(); + _cts = new CancellationTokenSource(); + _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); } /// @@ -347,61 +541,16 @@ namespace Modbus.Net get { return _keepConnect; } set { - TaskStop(); + PauseTimerAll(); _keepConnect = value; lock (_machines) { foreach (var machine in _machines) { - machine.KeepConnect = _keepConnect; + machine.Machine.KeepConnect = _keepConnect; } } - } - } - - /// - /// 获取间隔,毫秒 - /// - public int GetCycle - { - get { return _getCycle; } - set - { - if (value == _getCycle) return; - - if (value == Timeout.Infinite) - { - if (_timer != null) - { - _timer.Change(Timeout.Infinite, Timeout.Infinite); - _timer2.Change(Timeout.Infinite, Timeout.Infinite); - _timer.Dispose(); - _timer2.Dispose(); - _timer = null; - _timer2 = null; - } - } - else if (value < 0) return; - else - { - if (_timer != null) - { - _timer.Change(Timeout.Infinite, Timeout.Infinite); - _timer2.Change(Timeout.Infinite, Timeout.Infinite); - _timer.Dispose(); - _timer2.Dispose(); - _timer = null; - _timer2 = null; - } - if (value > 0) - { - _getCycle = value; - } - _timer = new Timer(MaintainTasks, null, 0, _getCycle); - _timer2 = new Timer(MaintainTasks2, null, _getCycle*2, _getCycle*2); - //调试行,调试时请注释上面两行并取消下面一行的注释,每台设备只会执行一次数据获取。 - //MaintainTasks(null); - } + ContinueTimerAll(); } } @@ -450,26 +599,23 @@ namespace Modbus.Net get { return _scheduler.MaximumConcurrencyLevel; } set { - TaskStop(); + PauseTimerAll(); _scheduler = new LimitedConcurrencyLevelTaskScheduler(value); + ContinueTimerAll(); } } - /// - /// 返回数据事件 - /// - public event ReturnValuesDelegate ReturnValues; - /// /// 添加一台设备 /// /// 设备 - public void AddMachine(BaseMachine machine) where TUnitKey : IEquatable + public void AddMachine(BaseMachine machine) + where TUnitKey : IEquatable { machine.KeepConnect = KeepConnect; lock (_machines) { - _machines.Add(machine); + _machines.Add(new TaskMachine(machine, _tasks) {TasksWithTimer = new List()}); } } @@ -477,7 +623,8 @@ namespace Modbus.Net /// 添加多台设备 /// /// 设备的列表 - public void AddMachines(IEnumerable> machines) where TUnitKey : IEquatable + public void AddMachines(IEnumerable> machines) + where TUnitKey : IEquatable { lock (_machines) { @@ -493,17 +640,10 @@ namespace Modbus.Net { try { - IMachineProperty machine; + TaskMachine machine; lock (_machines) { - machine = _machines.FirstOrDefault(p => p.Id.Equals(id)); - if (machine == null) - { - lock (_unlinkedMachines) - { - machine = _unlinkedMachines.FirstOrDefault(p => p.Id.Equals(id)); - } - } + machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(id)); } return machine as BaseMachine; } @@ -519,17 +659,10 @@ namespace Modbus.Net { try { - IMachineProperty machine; + TaskMachine machine; lock (_machines) { - machine = _machines.FirstOrDefault(p => p.ConnectionToken == connectionToken); - if (machine == null) - { - lock (_unlinkedMachines) - { - machine = _unlinkedMachines.FirstOrDefault(p => p.ConnectionToken == connectionToken); - } - } + machine = _machines.FirstOrDefault(p => p.Machine.ConnectionToken == connectionToken); } return machine as BaseMachine; } @@ -548,11 +681,7 @@ namespace Modbus.Net { lock (_machines) { - _machines.RemoveWhere(p => p.ConnectionToken == machineToken); - } - lock (_unlinkedMachines) - { - _unlinkedMachines.RemoveWhere(p => p.ConnectionToken == machineToken); + _machines.RemoveWhere(p => p.Machine.ConnectionToken == machineToken); } } @@ -564,55 +693,7 @@ namespace Modbus.Net { lock (_machines) { - _machines.RemoveWhere(p => p.Id.Equals(id)); - } - lock (_unlinkedMachines) - { - _unlinkedMachines.RemoveWhere(p => p.Id.Equals(id)); - } - } - - /// - /// 将设备指定为未连接 - /// - /// 设备的id - public void MoveMachineToUnlinked(TMachineKey id) - { - IEnumerable> machines; - lock (_machines) - { - machines = _machines.Where(c => c.Id.Equals(id)).ToList(); - if (!machines.Any()) return; - _machines.RemoveWhere(p => p.Id.Equals(id)); - } - lock (_unlinkedMachines) - { - foreach (var machine in machines) - { - _unlinkedMachines.Add(machine); - } - } - } - - /// - /// 将设备指定为已连接 - /// - /// 设备的id - public void MoveMachineToLinked(TMachineKey id) - { - IEnumerable> machines; - lock (_unlinkedMachines) - { - machines = _unlinkedMachines.Where(c => c.Id.Equals(id)).ToList(); - if (!machines.Any()) return; - _unlinkedMachines.RemoveWhere(p => p.Id.Equals(id)); - } - lock (_machines) - { - foreach (var machine in machines) - { - _machines.Add(machine); - } + _machines.RemoveWhere(p => p.Machine.Id.Equals(id)); } } @@ -624,192 +705,161 @@ namespace Modbus.Net { lock (_machines) { - _machines.Remove(machine); - } - lock (_unlinkedMachines) - { - _unlinkedMachines.Remove(machine); + _machines.RemoveWhere(p=>p.Machine.Equals(machine)); } } - /// - /// 已连接设备更新 - /// - /// - private void MaintainTasks(object sender) - { - AsyncHelper.RunSync(MaintainTasksAsync); - } - - /// - /// 未连接设备更新 - /// - /// - private void MaintainTasks2(object sender) - { - AsyncHelper.RunSync(MaintainTasks2Async); - } - - /// - /// 已连接设备更新 - /// - /// - private async Task MaintainTasksAsync() - { - try - { - var tasks = new List(); - var saveMachines = new HashSet>(); - IEnumerable> saveMachinesEnum; - lock (_machines) - { - saveMachines.UnionWith(_machines); - saveMachinesEnum = saveMachines.ToList(); - } - foreach (var machine in saveMachinesEnum) - { - var cts = new CancellationTokenSource(); - cts.CancelAfter(TimeSpan.FromSeconds(_getCycle*10)); - var task = _tasks.StartNew(() => RunTask(machine).WithCancellation(cts.Token)); - tasks.Add(task); - } - await Task.WhenAll(tasks); - } - catch (Exception) - { - //ignore - } - } - - /// - /// 未连接设备更新 - /// - /// - private async Task MaintainTasks2Async() - { - try - { - var tasks = new List(); - var saveMachines = new HashSet>(); - lock (_unlinkedMachines) - { - saveMachines.UnionWith(_unlinkedMachines); - } - foreach (var machine in saveMachines) - { - var cts = new CancellationTokenSource(); - cts.CancelAfter(TimeSpan.FromSeconds(_getCycle*10)); - var task = _tasks.StartNew(() => RunTask(machine).WithCancellation(cts.Token)); - tasks.Add(task); - } - await Task.WhenAll(tasks); - } - catch (Exception) - { - //ignore - } - } - - /// - /// 设置数据 - /// - /// 设备的连接标识 - /// 需要设置的数据 - /// 是否设置成功 - public async Task SetDatasAsync(string connectionToken, - Dictionary values) - { - IMachineProperty machine = null; - lock (_machines) - { - machine = _machines.FirstOrDefault(p => p.ConnectionToken == connectionToken); - } - if (machine == null) return false; - return await machine.InvokeMachineMethod>("SetDatasAsync", SetDataType, values); - } - - /// - /// 启动TaskManager - /// - public void TaskStart() - { - TaskStop(); - _cts = new CancellationTokenSource(); - _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); - GetCycle = TimeRestore.Restore; - } - - /// - /// 停止TaskManager - /// - public void TaskStop() + public bool InvokeTimerAll(TaskItem item) { lock (_machines) { - GetCycle = Timeout.Infinite; - _cts?.Cancel(); - if (_machines != null) + foreach (var machine in _machines) { - foreach (var machine in _machines) - { - machine.Disconnect(); - } + machine.InvokeTimer(item); } - _tasks = null; } + return true; } - /// - /// 执行对具体设备的数据更新 - /// - /// 设备的实例 - /// - protected virtual async Task RunTask(IMachineProperty machine) + public bool StopTimerAll() { - try + lock (_machines) { - var ans = await GetValue(machine); - ReturnValues?.Invoke(new TaskReturnDef + foreach (var machine in _machines) { - MachineId = machine.Id, - ReturnValues = ans - }); - } - catch (Exception e) - { - if (!machine.IsConnected) - { - MoveMachineToUnlinked(machine.Id); + machine.StopAllTimers(); } - ReturnValues?.Invoke(new TaskReturnDef - { - MachineId = machine.Id, - ReturnValues = null - }); } + return true; } - protected async Task> GetValue(IMachineProperty machine) + public bool StopTimerAll(string taskItemName) { - //调试代码,调试时取消下面一下代码的注释,会同步调用获取数据。 - //var ans = machine.GetDatas(); - //设置Cancellation Token - var cts = new CancellationTokenSource(); - //超时后取消任务 - cts.CancelAfter(TimeSpan.FromSeconds(_getCycle)); - //读取数据 - var ans = - await machine.InvokeMachineMethod>>("GetDatasAsync", - GetDataType).WithCancellation(cts.Token); - if (!machine.IsConnected) + lock (_machines) { - MoveMachineToUnlinked(machine.Id); + foreach (var machine in _machines) + { + machine.StopTimer(taskItemName); + } } - else + return true; + } + + public bool PauseTimerAll() + { + lock (_machines) { - MoveMachineToLinked(machine.Id); + foreach (var machine in _machines) + { + machine.PauseAllTimers(); + } } - return ans; + return true; + } + + public bool PauseTimerAll(string taskItemName) + { + lock (_machines) + { + foreach (var machine in _machines) + { + machine.PauseTimer(taskItemName); + } + } + return true; + } + + public bool ContinueTimerAll() + { + lock (_machines) + { + foreach (var machine in _machines) + { + machine.ContinueAllTimers(); + } + } + return true; + } + + public bool ConinueTimerAll(string taskItemName) + { + lock (_machines) + { + foreach (var machine in _machines) + { + machine.ContinueTimer(taskItemName); + } + } + return true; + } + + public async Task InvokeOnceAll(TaskItem item) + { + var tasks = new List>(); + lock (_machines) + { + foreach (var machine in _machines) + { + tasks.Add(machine.InvokeOnce(item)); + } + } + var ans = await Task.WhenAll(tasks); + return ans.All(p=>p); + } + + public async Task InvokeOnceForMachine(TMachineKey machineId, TaskItem item) + { + var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); + if (machine != null) + { + await machine.InvokeOnce(item); + return true; + } + return false; + } + + public bool InvokeTimerForMachine(TMachineKey machineId, TaskItem item) + { + var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); + if (machine != null) + { + machine.InvokeTimer(item); + return true; + } + return false; + } + + public bool StopTimerForMachine(TMachineKey machineId, string taskItemName) + { + var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); + if (machine != null) + { + machine.StopTimer(taskItemName); + return true; + } + return false; + } + + public bool PauseTimerForMachine(TMachineKey machineId, string taskItemName) + { + var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); + if (machine != null) + { + machine.PauseTimer(taskItemName); + return true; + } + return false; + } + + public bool ContinueTimerForMachine(TMachineKey machineId, string taskItemName) + { + var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); + if (machine != null) + { + machine.ContinueTimer(taskItemName); + return true; + } + return false; } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/TypeExtensions.cs b/Modbus.Net/src/Base.Common/TypeExtensions.cs new file mode 100644 index 0000000..282f839 --- /dev/null +++ b/Modbus.Net/src/Base.Common/TypeExtensions.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Modbus.Net +{ + public static class TypeExtensions + { + #region Public Methods + + /// + /// Looks for the method in the type matching the name and arguments. + /// + /// + /// + /// The name of the method to find. + /// + /// + /// The types of the method's arguments to match. + /// + /// + /// + /// Thrown if: + /// - The name of the method is not specified. + /// + public static MethodInfo GetRuntimeMethod(this Type type, string methodName, Type[] args, bool isGenericMethod) + { + if (ReferenceEquals(type, null)) + throw new NullReferenceException("The type has not been specified."); + + if (string.IsNullOrEmpty(methodName)) + throw new ArgumentNullException("methodName", "The name of the method has not been specified."); + + + var methods = type.GetRuntimeMethods().Where(methodInfo => string.Equals(methodInfo.Name, methodName, StringComparison.OrdinalIgnoreCase)).ToList(); + + if (!methods.Any()) + return null; // No methods have the specified name. + + if (isGenericMethod) + { + methods = methods.Where(method => method.IsGenericMethod).ToList(); + } + else + { + methods = methods.Where(method => !method.IsGenericMethod).ToList(); + } + + var ans = methods.Where(method => IsSignatureMatch(method, args)); + + if (ans.Count() <= 1) + { + return ans.Count() == 1 ? ans.Single() : null; + } + + // Oh noes, don't make me go there. + throw new NotImplementedException("Resolving overloaded methods is not implemented as of now."); + } + + #endregion + + #region Private Methods + + /// + /// Finds out if the provided arguments matches the specified method's signature. + /// + /// + /// + /// + private static bool IsSignatureMatch(MethodBase methodInfo, Type[] args) + { + Debug.Assert(!ReferenceEquals(methodInfo, null), "The methodInfo has not been specified."); + + + // Gets the parameters of the method to analyze. + ParameterInfo[] parameters = methodInfo.GetParameters(); + + int currentArgId = 0; + + foreach (ParameterInfo parameterInfo in parameters) + { + if (!ReferenceEquals(args, null) && currentArgId < args.Length) + { + // Find out if the types matchs. + if (parameterInfo.ParameterType == args[currentArgId]) + { + currentArgId++; + continue; // Yeah! Try the next one. + } + + // Is this a generic parameter? + if (parameterInfo.ParameterType.IsGenericParameter) + { + // Gets the base type of the generic parameter. + Type baseType = parameterInfo.ParameterType.GetTypeInfo().BaseType; + + + // TODO: This is not good v and works with the most simple situation. + // Does the base type match? + if (args[currentArgId].GetTypeInfo().BaseType == baseType) + { + currentArgId++; + continue; // Yeah! Go on to the next parameter. + } + } + } + + // Is this parameter optional or does it have a default value? + if (parameterInfo.IsOptional || parameterInfo.HasDefaultValue) + continue; // Uhum. So let's ignore this parameter for now. + + // No need to go further. It does not match :( + return false; + } + + // Ye! + return true; + } + + #endregion + } +} diff --git a/Samples/AnyType/Controllers/HomeController.cs b/Samples/AnyType/Controllers/HomeController.cs index 93b730f..ad7d7de 100644 --- a/Samples/AnyType/Controllers/HomeController.cs +++ b/Samples/AnyType/Controllers/HomeController.cs @@ -55,38 +55,39 @@ namespace AnyType.Controllers }; //初始化任务管理器 - task = new TaskManager(10, 300, true); + task = new TaskManager(10, true); //向任务管理器中添加设备 task.AddMachine(new ModbusMachine(ModbusType.Tcp, "192.168.3.10", addressUnits, true, 2, 0)); - //增加值返回时的处理函数 - task.ReturnValues += (returnValues) => + //启动任务 + task.InvokeTimerAll(new TaskItemGetData(returnValues => { //唯一的参数包含返回值,是一个唯一标识符(machine的第二个参数),返回值(类型ReturnUnit)的键值对。 if (returnValues.ReturnValues != null) { lock (values) { - var unitValues = from val in returnValues.ReturnValues select new Tuple(addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); + var unitValues = from val in returnValues.ReturnValues + select + new Tuple( + addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); values = from unitValue in unitValues - select - new TaskViewModel() - { - Id = unitValue.Item1.Id, - Name = unitValue.Item1.Name, - Address = unitValue.Item1.Address + "." + unitValue.Item1.SubAddress, - Value = unitValue.Item2 ?? 0, - Type = unitValue.Item1.DataType.Name - }; + select + new TaskViewModel() + { + Id = unitValue.Item1.Id, + Name = unitValue.Item1.Name, + Address = unitValue.Item1.Address + "." + unitValue.Item1.SubAddress, + Value = unitValue.Item2 ?? 0, + Type = unitValue.Item1.DataType.Name + }; } } else { Console.WriteLine($"ip {returnValues.MachineId} not return value"); } - }; - //启动任务 - task.TaskStart(); + }, 15000, 60000)); } [HttpGet] diff --git a/Samples/TaskManager/Controllers/HomeController.cs b/Samples/TaskManager/Controllers/HomeController.cs index d34abc4..484df23 100644 --- a/Samples/TaskManager/Controllers/HomeController.cs +++ b/Samples/TaskManager/Controllers/HomeController.cs @@ -47,38 +47,39 @@ namespace TaskManager.Controllers }; //初始化任务管理器 - task = new Modbus.Net.TaskManager(10, 300, true); + task = new Modbus.Net.TaskManager(10, true); //向任务管理器中添加设备 task.AddMachine(new ModbusMachine(ModbusType.Tcp, "192.168.3.10", addressUnits, true, 2, 0)); - //增加值返回时的处理函数 - task.ReturnValues += (returnValues) => + //启动任务 + task.InvokeTimerAll(new TaskItemGetData(returnValues => { //唯一的参数包含返回值,是一个唯一标识符(machine的第二个参数),返回值(类型ReturnUnit)的键值对。 if (returnValues.ReturnValues != null) - { + { lock (values) { - var unitValues = from val in returnValues.ReturnValues select new Tuple(addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); + var unitValues = from val in returnValues.ReturnValues + select + new Tuple( + addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); values = from unitValue in unitValues select - new TaskViewModel() - { - Id = unitValue.Item1.Id, - Name = unitValue.Item1.Name, - Address = unitValue.Item1.Address.ToString(), - Value = unitValue.Item2 ?? 0, - Type = unitValue.Item1.DataType.Name - }; + new TaskViewModel() + { + Id = unitValue.Item1.Id, + Name = unitValue.Item1.Name, + Address = unitValue.Item1.Address.ToString(), + Value = unitValue.Item2 ?? 0, + Type = unitValue.Item1.DataType.Name + }; } } else { Console.WriteLine($"ip {returnValues.MachineId} not return value"); } - }; - //启动任务 - task.TaskStart(); + }, 15000, 60000)); } [HttpGet] diff --git a/Tests/Modbus.Net.Tests/BaseTest.cs b/Tests/Modbus.Net.Tests/BaseTest.cs index c6b1249..46cb258 100644 --- a/Tests/Modbus.Net.Tests/BaseTest.cs +++ b/Tests/Modbus.Net.Tests/BaseTest.cs @@ -142,7 +142,7 @@ namespace Modbus.Net.Tests MachineName = "Test 2" }; - _taskManager = new TaskManager(10, 3000, true); + _taskManager = new TaskManager(10, true); _taskManager.AddMachine(_baseMachine); _taskManager.AddMachine(_baseMachine2); From 1461efa42f46d5948f76fbc7ffc6bae2c95b1af4 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Mon, 15 May 2017 15:26:00 +0800 Subject: [PATCH 11/62] 2017-05-15 update 2 Add comments. --- .../Modbus.Net.Modbus.csproj | 4 + .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 1 + .../Modbus.Net.Siemens.csproj | 4 + Modbus.Net/Modbus.Net/ComConnector.cs | 2 +- Modbus.Net/src/Base.Common/AsyncHelper.cs | 7 + Modbus.Net/src/Base.Common/BaseMachine.cs | 16 + Modbus.Net/src/Base.Common/CRC16.cs | 7 +- Modbus.Net/src/Base.Common/TaskManager.cs | 349 ++++++++++++++++-- Modbus.Net/src/Base.Common/TypeExtensions.cs | 6 + Modbus.Net/src/Base.Common/ValueHelper.cs | 3 +- 10 files changed, 362 insertions(+), 37 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index d0c29f2..fef1838 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -23,6 +23,10 @@ bin\Debug\net45\Modbus.Net.Modbus.xml + + + + diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index 3f38142..34e799c 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -25,6 +25,7 @@ + diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 3c27504..b863ece 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -22,6 +22,10 @@ bin\Debug\net45\Modbus.Net.Siemens.xml + + + + diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs index e5b29fd..f0efd88 100644 --- a/Modbus.Net/Modbus.Net/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/ComConnector.cs @@ -409,7 +409,7 @@ namespace Modbus.Net Array.Copy(data, 0, returndata, 0, i); return returndata; } - catch (Exception ex) + catch (Exception) { Dispose(); return null; diff --git a/Modbus.Net/src/Base.Common/AsyncHelper.cs b/Modbus.Net/src/Base.Common/AsyncHelper.cs index 456c170..842fd28 100644 --- a/Modbus.Net/src/Base.Common/AsyncHelper.cs +++ b/Modbus.Net/src/Base.Common/AsyncHelper.cs @@ -55,6 +55,13 @@ namespace Modbus.Net return task.ContinueWith(t => t.GetAwaiter().GetResult(), token); } + /// + /// Add a CancellationToken to async task + /// + /// type of a task + /// Task + /// Cancellation token + /// Task with cancellation token public static Task WithCancellation(this Task task, CancellationToken token) { diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 757df30..6f8bf21 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -662,6 +662,10 @@ namespace Modbus.Net return BaseUtility.Disconnect(); } + /// + /// 获取设备的Id,字符串格式 + /// + /// public string GetMachineIdString() { return Id.ToString(); @@ -821,12 +825,20 @@ namespace Modbus.Net /// public UnitExtend UnitExtend { get; set; } + /// + /// 两个地址是否一致 + /// + /// 另一个地址 + /// 是否一致 public bool Equals(AddressUnit other) { return (Area.ToUpper() == other.Area.ToUpper() && Address == other.Address) || Id.Equals(other.Id); } } + /// + /// 没有Id的设备属性 + /// public interface IMachinePropertyWithoutKey { /// @@ -888,6 +900,10 @@ namespace Modbus.Net /// 是否断开成功 bool Disconnect(); + /// + /// 获取设备的Id的字符串 + /// + /// string GetMachineIdString(); } diff --git a/Modbus.Net/src/Base.Common/CRC16.cs b/Modbus.Net/src/Base.Common/CRC16.cs index 67594dc..5303dba 100644 --- a/Modbus.Net/src/Base.Common/CRC16.cs +++ b/Modbus.Net/src/Base.Common/CRC16.cs @@ -44,7 +44,6 @@ namespace Modbus.Net /// /// 发送或返回的命令,CRC码除外 /// 存储CRC码的字节的数组 - /// 生成的CRC码 public short GetCRC(byte[] message, ref byte[] Rcvbuf) { int IX, IY, CRC; @@ -83,7 +82,7 @@ namespace Modbus.Net /// /// CRC校验 /// - /// ST开头,&&结尾 + /// 需要校验的字节数组 /// 十六进制数 public bool CrcEfficacy(byte[] byteframe) { @@ -149,15 +148,13 @@ namespace Modbus.Net decByteTotal = 255 - decByteTotal + 1; decByteTotal = decByteTotal & 255; - int a, b = 0; - string hexByte = "", hexTotal = ""; double i; for (i = 0; decByteTotal > 0; i++) { //b = Convert.ToInt32(System.Math.Pow(16.0, i)); - a = decByteTotal%16; + var a = decByteTotal%16; decByteTotal /= 16; if (a <= 9) hexByte = a.ToString(); diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 00ae740..e73aa17 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -25,10 +25,19 @@ namespace Modbus.Net /// public class DataReturnDef where TMachineKey : IEquatable { + /// + /// 设备的Id + /// public TMachineKey MachineId { get; set; } + /// + /// 返回的数据值 + /// public Dictionary ReturnValues { get; set; } } + /// + /// Limited concurrency level task scheduler + /// public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler { /// @@ -192,20 +201,45 @@ namespace Modbus.Net } } + /// + /// 具有任务管理的设备 + /// + /// 设备的Id类型 public class TaskMachine where TMachineKey : IEquatable { - private TaskFactory _tasks { get; } + /// + /// 任务工厂 + /// + private readonly TaskFactory _tasks; + /// + /// 构造函数 + /// + /// 设备 + /// 任务工厂 public TaskMachine(IMachineProperty machine, TaskFactory taskFactory) { Machine = machine; _tasks = taskFactory; + TasksWithTimer = new List(); } + /// + /// 设备 + /// public IMachineProperty Machine { get; } - public List TasksWithTimer { get; set; } + /// + /// 任务调度器 + /// + public List TasksWithTimer { get; } + /// + /// 定时方式启动任务 + /// + /// 任务返回值的类型 + /// 任务 + /// 任务是否执行成功 public bool InvokeTimer(TaskItem task) { task.DetectConnected = () => Machine.IsConnected; @@ -221,6 +255,11 @@ namespace Modbus.Net return false; } + /// + /// 停止任务 + /// + /// 任务的名称 + /// 是否停止成功 public bool StopTimer(string taskItemName) { if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName)) @@ -233,6 +272,10 @@ namespace Modbus.Net return false; } + /// + /// 停止所有任务 + /// + /// 是否停止成功 public bool StopAllTimers() { bool ans = true; @@ -243,6 +286,11 @@ namespace Modbus.Net return ans; } + /// + /// 暂时任务 + /// + /// 任务的名称 + /// 是否暂停成功 public bool PauseTimer(string taskItemName) { if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName)) @@ -254,6 +302,10 @@ namespace Modbus.Net return false; } + /// + /// 暂停所有任务 + /// + /// 是否暂停成功 public bool PauseAllTimers() { bool ans = true; @@ -264,6 +316,11 @@ namespace Modbus.Net return ans; } + /// + /// 恢复任务 + /// + /// 任务的名称 + /// 是否恢复任务 public bool ContinueTimer(string taskItemName) { if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName)) @@ -275,6 +332,10 @@ namespace Modbus.Net return false; } + /// + /// 恢复所有任务 + /// + /// 是否恢复成功 public bool ContinueAllTimers() { bool ans = true; @@ -285,12 +346,18 @@ namespace Modbus.Net return ans; } + /// + /// 执行任务一次 + /// + /// 任务返回值的类型 + /// 任务 + /// 任务是否执行成功 public async Task InvokeOnce(TaskItem task) { if (Machine.IsConnected) { var ans = await task.Invoke(Machine, _tasks, task.Params); - task.Return(ans); + task.Return?.Invoke(ans); return true; } return false; @@ -311,17 +378,40 @@ namespace Modbus.Net } } + /// + /// 任务的接口 + /// public interface ITaskItem { + /// + /// 任务的名称 + /// string Name { get; set; } + /// + /// 启动计时器 + /// + /// bool StartTimer(); + /// + /// 停止计时器 + /// + /// bool StopTimer(); } + /// + /// 获取数据的预定义任务 + /// public class TaskItemGetData : TaskItem { + /// + /// 构造函数 + /// + /// 返回值的处理函数 + /// 循环间隔(毫秒) + /// 设备离线时的循环间隔(毫秒) public TaskItemGetData(Action returnFunc, int getCycle, int sleepCycle) { Name = "GetDatas"; @@ -346,10 +436,18 @@ namespace Modbus.Net TimerTime = getCycle; } } - + + /// + /// 写入数据的预定义任务 + /// public class TaskItemSetData : TaskItem { - public TaskItemSetData(Dictionary values) + /// + /// 构造函数 + /// + /// 写入的值 + /// 返回值的处理函数 + public TaskItemSetData(Dictionary values, Action returnFunc = null) { Name = "SetDatas"; Invoke = Invoke = async (machine, tasks, parameters) => @@ -364,50 +462,106 @@ namespace Modbus.Net return ans; }; Params = new object[]{values}; + Return = returnFunc; } } + /// + /// 任务 + /// + /// 任务返回值的类型 public class TaskItem : ITaskItem, IEquatable> { + /// + /// 名称 + /// public string Name { get; set; } + /// + /// 定时器 + /// private Timer Timer { get; set; } + /// + /// 定时器的时间 + /// public int TimerTime { get; set; } + /// + /// 离线定时器 + /// private Timer TimerDisconnected { get; set; } + /// + /// 离线定时器的时间 + /// public int TimerDisconnectedTime { get; set; } + /// + /// 执行的任务 + /// public Func> Invoke { get; set; } + /// + /// 检测设备的在线状态 + /// internal Func DetectConnected { get; set; } + /// + /// 任务执行的参数 + /// public object[] Params { get; set; } + /// + /// 返回值的处理函数 + /// public Action Return { get; set; } + /// + /// 获取设备 + /// internal Func GetMachine { get; set; } + /// + /// 获取任务工厂 + /// internal Func GetTaskFactory { get; set; } + /// + /// 是否相等 + /// + /// 另一个实例 + /// 是否相等 public bool Equals(TaskItem other) { return Name == other?.Name; } + /// + /// 启动定时器 + /// + /// 是否成功 public bool StartTimer() { ActivateTimerDisconnected(); return true; } + /// + /// 激活定时器 + /// private void ActivateTimer() { Timer = new Timer(async state => { if (!DetectConnected()) TimerChangeToDisconnect(); var ans = await Invoke(GetMachine(),GetTaskFactory(),Params); - Return(ans); + Return?.Invoke(ans); }, null, 0, TimerTime); } + /// + /// 反激活定时器 + /// private void DeactivateTimer() { Timer.Dispose(); Timer = null; } + /// + /// 激活离线定时器 + /// private void ActivateTimerDisconnected() { TimerDisconnected = new Timer(async state => @@ -417,12 +571,19 @@ namespace Modbus.Net }, null, 0, TimerDisconnectedTime); } + /// + /// 反激活离线定时器 + /// private void DeactivateTimerDisconnected() { TimerDisconnected.Dispose(); TimerDisconnected = null; } + /// + /// 将定时器切换至在线 + /// + /// private bool TimerChangeToConnect() { DeactivateTimerDisconnected(); @@ -430,6 +591,10 @@ namespace Modbus.Net return true; } + /// + /// 将定时器切换至离线 + /// + /// private bool TimerChangeToDisconnect() { DeactivateTimer(); @@ -437,6 +602,10 @@ namespace Modbus.Net return true; } + /// + /// 停止定时器 + /// + /// public bool StopTimer() { DeactivateTimer(); @@ -450,27 +619,51 @@ namespace Modbus.Net /// public class TaskManager : TaskManager { + /// + /// 构造一个TaskManager + /// + /// 同时可以运行的任务数 + /// 读取数据后是否保持连接 + /// 获取与设置数据的方式 public TaskManager(int maxRunningTask, bool keepConnect, MachineDataType dataType = MachineDataType.CommunicationTag) : base(maxRunningTask, keepConnect, dataType) { } + /// + /// 添加一台设备 + /// + /// 设备 public void AddMachine(BaseMachine machine) { base.AddMachine(machine); } + /// + /// 添加多台设备 + /// + /// 多台设备 public void AddMachines(IEnumerable machines) { base.AddMachines(machines); } + /// + /// 通过Id获取设备 + /// + /// 设备Id + /// 获取的设备 public BaseMachine GetMachineById(string id) { return base.GetMachineById(id) as BaseMachine; } + /// + /// 通过通讯标志获取设备 + /// + /// 通讯标志 + /// 获取的设备 public BaseMachine GetMachineByConnectionToken(string connectionToken) { return base.GetMachineByConnectionToken(connectionToken) as BaseMachine; @@ -480,7 +673,7 @@ namespace Modbus.Net /// /// 任务调度器 /// - /// + /// 设备Id的类型 public class TaskManager where TMachineKey : IEquatable { /// @@ -488,6 +681,9 @@ namespace Modbus.Net /// private readonly HashSet> _machines; + /// + /// 全局任务取消标志 + /// private CancellationTokenSource _cts; /// @@ -554,6 +750,9 @@ namespace Modbus.Net } } + /// + /// 设备读写设备的关键字 + /// public MachineDataType MachineDataType { set @@ -588,7 +787,13 @@ namespace Modbus.Net } } + /// + /// 设备读数据的关键字 + /// public MachineGetDataType GetDataType { get; set; } + /// + /// 设备写数据的关键字 + /// public MachineSetDataType SetDataType { get; set; } /// @@ -615,7 +820,7 @@ namespace Modbus.Net machine.KeepConnect = KeepConnect; lock (_machines) { - _machines.Add(new TaskMachine(machine, _tasks) {TasksWithTimer = new List()}); + _machines.Add(new TaskMachine(machine, _tasks)); } } @@ -635,6 +840,12 @@ namespace Modbus.Net } } + /// + /// 通过Id获取设备 + /// + /// 设备地址Id的类型 + /// 设备的Id + /// 获取设备 public BaseMachine GetMachineById(TMachineKey id) where TUnitKey : IEquatable { @@ -654,6 +865,12 @@ namespace Modbus.Net } } + /// + /// 通过通讯标志获取设备 + /// + /// 设备地址Id的类型 + /// 通讯标志 + /// 获取的数据 public BaseMachine GetMachineByConnectionToken(string connectionToken) where TUnitKey : IEquatable { @@ -709,78 +926,117 @@ namespace Modbus.Net } } + /// + /// 所有设备执行定时任务 + /// + /// 任务返回值的类型 + /// 任务 + /// 所有任务是否执行成功 public bool InvokeTimerAll(TaskItem item) { + var ans = true; lock (_machines) { foreach (var machine in _machines) { - machine.InvokeTimer(item); + ans &= machine.InvokeTimer(item); } } - return true; + return ans; } + /// + /// 所有设备停止执行所有任务 + /// + /// 所有任务是否停止成功 public bool StopTimerAll() { + var ans = true; lock (_machines) { foreach (var machine in _machines) { - machine.StopAllTimers(); + ans &= machine.StopAllTimers(); } } - return true; + return ans; } + /// + /// 所有设备停止执行某一个任务 + /// + /// 任务名称 + /// 任务是否停止成功 public bool StopTimerAll(string taskItemName) { + var ans = true; lock (_machines) { foreach (var machine in _machines) { - machine.StopTimer(taskItemName); + ans &= machine.StopTimer(taskItemName); } } - return true; + return ans; } + /// + /// 所有设备暂停执行所有任务 + /// + /// 任务是否暂停成功 public bool PauseTimerAll() { + var ans = true; lock (_machines) { foreach (var machine in _machines) { - machine.PauseAllTimers(); + ans &= machine.PauseAllTimers(); } } - return true; + return ans; } + /// + /// 所有设备暂停执行某一个任务 + /// + /// 任务的名称 + /// 任务是否暂停成功 public bool PauseTimerAll(string taskItemName) { + var ans = true; lock (_machines) { foreach (var machine in _machines) { - machine.PauseTimer(taskItemName); + ans &= machine.PauseTimer(taskItemName); } } - return true; + return ans; } + /// + /// 所有设备继续执行所有任务 + /// + /// 所有任务是否继续执行成功 public bool ContinueTimerAll() { + var ans = true; lock (_machines) { foreach (var machine in _machines) { - machine.ContinueAllTimers(); + ans &= machine.ContinueAllTimers(); } } - return true; + return ans; } + /// + /// 所有设备继续执行某一个任务 + /// + /// 任务的名称 + /// 任务是否继续执行成功 public bool ConinueTimerAll(string taskItemName) { lock (_machines) @@ -793,6 +1049,12 @@ namespace Modbus.Net return true; } + /// + /// 所有设备执行一个一次性任务 + /// + /// 任务的返回值类型 + /// 任务 + /// 任务是否执行成功 public async Task InvokeOnceAll(TaskItem item) { var tasks = new List>(); @@ -807,57 +1069,84 @@ namespace Modbus.Net return ans.All(p=>p); } + /// + /// 某个设备执行一个一次性任务 + /// + /// 任务的返回值类型 + /// 设备的Id + /// 任务 + /// 任务是否执行成功 public async Task InvokeOnceForMachine(TMachineKey machineId, TaskItem item) { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) { - await machine.InvokeOnce(item); - return true; + return await machine.InvokeOnce(item); } return false; } + /// + /// 某个设备执行一个定时任务 + /// + /// 任务的返回值类型 + /// 设备的Id + /// 任务 + /// 任务是否执行成功 public bool InvokeTimerForMachine(TMachineKey machineId, TaskItem item) { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) { - machine.InvokeTimer(item); - return true; + return machine.InvokeTimer(item); } return false; } + /// + /// 某个设备停止一个定时任务 + /// + /// 任务的Id + /// 任务的名称 + /// 任务是否停止成功 public bool StopTimerForMachine(TMachineKey machineId, string taskItemName) { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) { - machine.StopTimer(taskItemName); - return true; + return machine.StopTimer(taskItemName); } return false; } + /// + /// 某个设备暂停一个定时任务 + /// + /// 任务的Id + /// 任务的名称 + /// 任务是否暂停成功 public bool PauseTimerForMachine(TMachineKey machineId, string taskItemName) { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) { - machine.PauseTimer(taskItemName); - return true; + return machine.PauseTimer(taskItemName); } return false; } + /// + /// 某个设备继续进行一个定时任务 + /// + /// 任务的Id + /// 任务的名称 + /// 任务是否继续运行成功 public bool ContinueTimerForMachine(TMachineKey machineId, string taskItemName) { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) { - machine.ContinueTimer(taskItemName); - return true; + return machine.ContinueTimer(taskItemName); } return false; } diff --git a/Modbus.Net/src/Base.Common/TypeExtensions.cs b/Modbus.Net/src/Base.Common/TypeExtensions.cs index 282f839..fb8778d 100644 --- a/Modbus.Net/src/Base.Common/TypeExtensions.cs +++ b/Modbus.Net/src/Base.Common/TypeExtensions.cs @@ -8,6 +8,9 @@ using System.Threading.Tasks; namespace Modbus.Net { + /// + /// Extensions of Reflection + /// public static class TypeExtensions { #region Public Methods @@ -22,6 +25,9 @@ namespace Modbus.Net /// /// The types of the method's arguments to match. /// + /// + /// Is method Generic Method. + /// /// /// /// Thrown if: diff --git a/Modbus.Net/src/Base.Common/ValueHelper.cs b/Modbus.Net/src/Base.Common/ValueHelper.cs index c5c953e..01b34b3 100644 --- a/Modbus.Net/src/Base.Common/ValueHelper.cs +++ b/Modbus.Net/src/Base.Common/ValueHelper.cs @@ -1244,7 +1244,8 @@ namespace Modbus.Net /// 设置对应数字中相应位置的bit的值 /// /// byte数子 - /// 设置位置 + /// 设置的位置 + /// 设置的子位置 /// 设置bit大小,true为1,false为0 /// 设置是否成功 public override bool SetBit(byte[] number, int pos, int subPos, bool setBit) From 34b0777cc7e54073cf55725201924b1720f2cc9e Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 16 May 2017 17:46:03 +0800 Subject: [PATCH 12/62] 2017-05-16 update 1 Add multistation COM support. --- .../Modbus.Net.Modbus/ModbusAsciiProtocal.cs | 2 +- .../ModbusAsciiProtocalLinker.cs | 2 +- .../Modbus.Net.Modbus/ModbusRtuProtocal.cs | 2 +- .../ModbusRtuProtocalLinker.cs | 2 +- .../ModbusTcpProtocalLinker.cs | 2 +- .../Modbus.Net.Siemens/SiemensPpiProtocal.cs | 2 +- .../SiemensPpiProtocalLinker.cs | 4 +- .../Modbus.Net.Siemens/SiemensTcpProtocal.cs | 4 +- .../SiemensTcpProtocalLinker.cs | 2 +- Modbus.Net/Modbus.Net/ComConnector.cs | 139 ++++++++++------- Modbus.Net/Modbus.Net/ComProtocalLinker.cs | 27 +++- .../src/Base.Common/TcpProtocalLinker.cs | 16 +- .../Modbus.Net.Tests/Modbus.Net.Tests.csproj | 1 + .../ModbusMultiStationTest.cs | 140 ++++++++++++++++++ 14 files changed, 277 insertions(+), 68 deletions(-) create mode 100644 Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs index f75400c..bf93d71 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs @@ -15,7 +15,7 @@ namespace Modbus.Net.Modbus public ModbusAsciiProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { - ProtocalLinker = new ModbusAsciiProtocalLinker(com); + ProtocalLinker = new ModbusAsciiProtocalLinker(com, slaveAddress); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs index 8952917..f314fca 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs @@ -8,7 +8,7 @@ namespace Modbus.Net.Modbus /// public class ModbusAsciiProtocalLinker : ComProtocalLinker { - public ModbusAsciiProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8) + public ModbusAsciiProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs index 53fab41..aace433 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs @@ -15,7 +15,7 @@ namespace Modbus.Net.Modbus public ModbusRtuProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { - ProtocalLinker = new ModbusRtuProtocalLinker(com); + ProtocalLinker = new ModbusRtuProtocalLinker(com, slaveAddress); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs index a5a089d..0d91f6b 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs @@ -7,7 +7,7 @@ namespace Modbus.Net.Modbus /// public class ModbusRtuProtocalLinker : ComProtocalLinker { - public ModbusRtuProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8) + public ModbusRtuProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs index f49667c..87a8a22 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs @@ -7,7 +7,7 @@ namespace Modbus.Net.Modbus /// public class ModbusTcpProtocalLinker : TcpProtocalLinker { - public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"])) + public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"] ?? "502")) { } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs index 1585154..d91aa63 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs @@ -47,7 +47,7 @@ namespace Modbus.Net.Siemens public override async Task ConnectAsync() { - ProtocalLinker = new SiemensPpiProtocalLinker(_com); + ProtocalLinker = new SiemensPpiProtocalLinker(_com, SlaveAddress); var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress); var outputStruct = await await diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs index 0ddb7ad..b8d93f1 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs @@ -9,8 +9,8 @@ namespace Modbus.Net.Siemens /// public class SiemensPpiProtocalLinker : ComProtocalLinker { - public SiemensPpiProtocalLinker(string com) - : base(com, 9600, Parity.Even, StopBits.One, 8) + public SiemensPpiProtocalLinker(string com, int slaveAddress) + : base(com, 9600, Parity.Even, StopBits.One, 8, slaveAddress) { } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs index cc44acd..3150fa6 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs @@ -24,7 +24,7 @@ namespace Modbus.Net.Siemens } public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, - ushort maxPdu, string ip) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ip, 0) + ushort maxPdu, string ip) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"])) { } @@ -85,7 +85,7 @@ namespace Modbus.Net.Siemens public override async Task ConnectAsync() { _connectTryCount++; - ProtocalLinker = _port == 0 ? new SiemensTcpProtocalLinker(_ip) : new SiemensTcpProtocalLinker(_ip, _port); + ProtocalLinker = new SiemensTcpProtocalLinker(_ip, _port); if (!await ProtocalLinker.ConnectAsync()) return false; _connectTryCount = 0; var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst); diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs index 23f4b62..ffbeabf 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs @@ -9,7 +9,7 @@ namespace Modbus.Net.Siemens public class SiemensTcpProtocalLinker : TcpProtocalLinker { public SiemensTcpProtocalLinker(string ip) - : base(ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"])) + : this(ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"] ?? "102")) { } diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs index f0efd88..257289f 100644 --- a/Modbus.Net/Modbus.Net/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/ComConnector.cs @@ -1,12 +1,19 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.IO.Ports; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Modbus.Net { + public class SerialPortLock : SerialPort + { + public object Lock { get; set; } = new object(); + } + /// /// 串口通讯类 /// @@ -14,6 +21,9 @@ namespace Modbus.Net { public delegate byte[] GetDate(byte[] bts); + private static Dictionary Connectors { get; } = new Dictionary(); + private static Dictionary Linkers { get; } = new Dictionary(); + private readonly int _baudRate; //private GetDate mygetDate; @@ -22,19 +32,19 @@ namespace Modbus.Net private readonly Parity _parity; private readonly StopBits _stopBits; private readonly int _timeoutTime; + private readonly string _slave; - private SerialPort _serialPort1; - - private bool m_disposed = true; + private bool m_disposed = false; public ComConnector(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int timeoutTime) { - _com = com; + _com = com.Split(':')[0]; _timeoutTime = timeoutTime; _baudRate = baudRate; _parity = parity; _stopBits = stopBits; _dataBits = dataBits; + _slave = com.Split(':')[1]; //端口号 //读超时 @@ -42,27 +52,18 @@ namespace Modbus.Net //奇偶校验 //停止位 //数据位 + //从站号标识 } - public override string ConnectionToken => _com; + public override string ConnectionToken => _slave + ":" + _com; - private SerialPort SerialPort1 + private SerialPortLock SerialPort { get { - if (_serialPort1 == null) - { - _serialPort1 = new SerialPort - { - PortName = _com, - BaudRate = _baudRate, - Parity = _parity, - StopBits = _stopBits, - DataBits = _dataBits, - ReadTimeout = _timeoutTime - }; - } - return _serialPort1; + if (Connectors.ContainsKey(_com)) + return Connectors[_com]; + return null; } } @@ -71,7 +72,7 @@ namespace Modbus.Net /// public void Dispose() { - Dispose(true); + Dispose(true); //.NET Framework 类库 // GC..::.SuppressFinalize 方法 //请求系统不要调用指定对象的终结器。 @@ -93,17 +94,17 @@ namespace Modbus.Net Array.Clear(readBuf, 0, readBuf.Length); int nReadLen, nBytelen; - if (SerialPort1.IsOpen == false) + if (SerialPort.IsOpen == false) return -1; nBytelen = 0; - SerialPort1.ReadTimeout = HowTime; + SerialPort.ReadTimeout = HowTime; try { - while (SerialPort1.BytesToRead > 0) + while (SerialPort.BytesToRead > 0) { - readBuf[nBytelen] = (byte) SerialPort1.ReadByte(); + readBuf[nBytelen] = (byte) SerialPort.ReadByte(); var bTmp = new byte[bufRoom]; Array.Clear(bTmp, 0, bTmp.Length); @@ -139,16 +140,16 @@ namespace Modbus.Net sbyte nBytelen; //long nByteRead; - if (SerialPort1.IsOpen == false) + if (SerialPort.IsOpen == false) return 0; nBytelen = 0; - SerialPort1.ReadTimeout = ByteTime; + SerialPort.ReadTimeout = ByteTime; - while (nBytelen < ReadRoom - 1 && SerialPort1.BytesToRead > 0) + while (nBytelen < ReadRoom - 1 && SerialPort.BytesToRead > 0) { try { - ReadBuf[nBytelen] = (byte) SerialPort1.ReadByte(); + ReadBuf[nBytelen] = (byte) SerialPort.ReadByte(); nBytelen++; // add one } catch (Exception ex) @@ -251,18 +252,23 @@ namespace Modbus.Net // Release managed resources } // Release unmanaged resources - if (_serialPort1 != null) + if (SerialPort != null) { - try + if (Linkers.Values.Count(p => p == _com) <= 1) { - _serialPort1.Close(); + try + { + SerialPort.Close(); + } + catch (Exception) + { + //ignore + } + SerialPort.Dispose(); + Connectors[_com] = null; + Connectors.Remove(_com); } - catch (Exception) - { - //ignore - } - _serialPort1.Dispose(); - _serialPort1 = null; + Linkers.Remove(_slave); } m_disposed = true; } @@ -283,12 +289,11 @@ namespace Modbus.Net { get { - if (_serialPort1 != null && !SerialPort1.IsOpen) + if (SerialPort != null && !SerialPort.IsOpen) { - _serialPort1.Dispose(); - _serialPort1 = null; + SerialPort.Dispose(); } - return _serialPort1 != null && _serialPort1.IsOpen; + return SerialPort != null && SerialPort.IsOpen && Linkers.ContainsKey(_slave); } } @@ -296,7 +301,23 @@ namespace Modbus.Net { try { - SerialPort1.Open(); + if (!Connectors.ContainsKey(_com)) + { + Connectors.Add(_com, new SerialPortLock + { + PortName = _com, + BaudRate = _baudRate, + Parity = _parity, + StopBits = _stopBits, + DataBits = _dataBits, + ReadTimeout = _timeoutTime + }); + } + if (!Linkers.ContainsKey(_slave)) + { + Linkers.Add(_slave, _com); + } + SerialPort.Open(); return true; } catch (Exception e) @@ -312,7 +333,7 @@ namespace Modbus.Net public override bool Disconnect() { - if (SerialPort1 != null) + if (Linkers.ContainsKey(_slave) && Connectors.ContainsKey(_com)) { try { @@ -343,19 +364,22 @@ namespace Modbus.Net { try { - if (!SerialPort1.IsOpen) + if (!SerialPort.IsOpen) { try { - SerialPort1.Open(); + SerialPort.Open(); } catch (Exception) { Dispose(); - SerialPort1.Open(); + SerialPort.Open(); } } - SerialPort1.Write(sendbytes, 0, sendbytes.Length); + lock (SerialPort.Lock) + { + SerialPort.Write(sendbytes, 0, sendbytes.Length); + } return ReadMsg(); } catch @@ -374,7 +398,22 @@ namespace Modbus.Net { try { - SerialPort1.Write(sendbytes, 0, sendbytes.Length); + if (!SerialPort.IsOpen) + { + try + { + SerialPort.Open(); + } + catch (Exception) + { + Dispose(); + SerialPort.Open(); + } + } + lock (SerialPort.Lock) + { + SerialPort.Write(sendbytes, 0, sendbytes.Length); + } return true; } catch (Exception) @@ -397,9 +436,9 @@ namespace Modbus.Net { try { - if (!SerialPort1.IsOpen) + if (!SerialPort.IsOpen) { - SerialPort1.Open(); + SerialPort.Open(); } byte[] data; diff --git a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs index 95e61a5..13d4461 100644 --- a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs @@ -15,8 +15,8 @@ namespace Modbus.Net /// 校验位 /// 停止位 /// 数据位 - protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits) - : this(ConfigurationManager.AppSettings["COM"], baudRate, parity, stopBits, dataBits) + protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits, int slaveAddress) + : this(ConfigurationManager.AppSettings["COM"], baudRate, parity, stopBits, dataBits, slaveAddress) { } @@ -28,10 +28,27 @@ namespace Modbus.Net /// 校验位 /// 停止位 /// 数据位 - protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits) + protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, + int slaveAddress) + : this( + com, baudRate, parity, stopBits, dataBits, + int.Parse(ConfigurationManager.AppSettings["ComConnectionTimeout"] ?? "3000"), slaveAddress) { - //初始化连对象 - BaseConnector = new ComConnector(com, baudRate, parity, stopBits, dataBits, int.Parse(ConfigurationManager.AppSettings["ComConnectionTimeout"])); + } + + /// + /// 构造器 + /// + /// 串口端口号 + /// 波特率 + /// 校验位 + /// 停止位 + /// 数据位 + /// 超时时间 + protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, + int connectionTimeout, int slaveAddress) + { + BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, connectionTimeout); } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs index 92cb4b0..b353cd8 100644 --- a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs @@ -12,7 +12,8 @@ namespace Modbus.Net /// /// 构造器 /// - protected TcpProtocalLinker() : this(ConfigurationManager.AppSettings["IP"], int.Parse(ConfigurationManager.AppSettings["ModbusPort"])) + protected TcpProtocalLinker(int port) + : this(ConfigurationManager.AppSettings["IP"], port) { } @@ -22,9 +23,20 @@ namespace Modbus.Net /// Ip地址 /// 端口 protected TcpProtocalLinker(string ip, int port) + : this(ip, port, int.Parse(ConfigurationManager.AppSettings["IPConnectionTimeout"] ?? "5000")) + { + } + + /// + /// 构造器 + /// + /// Ip地址 + /// 端口 + /// 超时时间 + protected TcpProtocalLinker(string ip, int port, int connectionTimeout) { //初始化连接对象 - BaseConnector = new TcpConnector(ip, port, int.Parse(ConfigurationManager.AppSettings["IPConnectionTimeout"])); + BaseConnector = new TcpConnector(ip, port, connectionTimeout); } } } \ No newline at end of file diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index aaf4bb9..a3c5572 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -58,6 +58,7 @@ + diff --git a/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs b/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs new file mode 100644 index 0000000..f86fac3 --- /dev/null +++ b/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Modbus.Net.Modbus; + +namespace Modbus.Net.Tests +{ + [TestClass] + public class ModbusMultiStationTest + { + private BaseMachine _modbusRtuMachine1; + + private BaseMachine _modbusRtuMachine2; + + [TestInitialize] + public void Init() + { + _modbusRtuMachine1 = new ModbusMachine(ModbusType.Rtu, "COM1", null, true, 1, 0); + _modbusRtuMachine2 = new ModbusMachine(ModbusType.Rtu, "COM1", null, true, 2, 0); + } + + [TestMethod] + public async Task Get() + { + var addresses = new List + { + new AddressUnit + { + Id = "0", + Area = "4X", + Address = 2, + SubAddress = 0, + CommunicationTag = "A1", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "1", + Area = "4X", + Address = 3, + SubAddress = 0, + CommunicationTag = "A2", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "2", + Area = "4X", + Address = 4, + SubAddress = 0, + CommunicationTag = "A3", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "3", + Area = "4X", + Address = 5, + SubAddress = 0, + CommunicationTag = "A4", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "4", + Area = "4X", + Address = 6, + SubAddress = 0, + CommunicationTag = "A5", + DataType = typeof(uint) + }, + new AddressUnit + { + Id = "5", + Area = "4X", + Address = 8, + SubAddress = 0, + CommunicationTag = "A6", + DataType = typeof(uint) + } + }; + + _modbusRtuMachine1.GetAddresses = addresses.ToList(); + _modbusRtuMachine2.GetAddresses = addresses.ToList(); + + await _modbusRtuMachine1.SetDatasAsync(MachineSetDataType.CommunicationTag, new Dictionary() + { + { + "A1", 70 + }, + { + "A2", 71 + }, + { + "A3", 72 + }, + { + "A4", 73 + }, + { + "A5", 717870 + }, + { + "A6", 717871 + }, + }); + await _modbusRtuMachine2.SetDatasAsync(MachineSetDataType.CommunicationTag, new Dictionary() + { + { + "A1", 74 + }, + { + "A2", 75 + }, + { + "A3", 76 + }, + { + "A4", 77 + }, + { + "A5", 717873 + }, + { + "A6", 717874 + }, + }); + var ans = await _modbusRtuMachine1.GetDatasAsync(MachineGetDataType.CommunicationTag); + var ans2 = await _modbusRtuMachine2.GetDatasAsync(MachineGetDataType.CommunicationTag); + + _modbusRtuMachine1.Disconnect(); + _modbusRtuMachine2.Disconnect(); + + Assert.AreEqual(ans["A1"].PlcValue, 70); + Assert.AreEqual(ans2["A1"].PlcValue, 74); + } + } +} From b61ea1759a1769e4d71ab836a605e9a6bebc2e04 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 17 May 2017 11:18:21 +0800 Subject: [PATCH 13/62] 2017-05-17 update 1 Add Comments and Reformat code. --- Modbus.Net/Modbus.Net.Core/App.config | 19 +- .../Modbus.Net.Core/ConfigurationManager.cs | 27 +- .../AddressTranslatorModbus.cs | 3 + .../ModbusAsciiProtocalLinker.cs | 7 +- .../Modbus.Net.Modbus/ModbusProtocal.cs | 8 +- .../ModbusProtocalLinkerBytesExtend.cs | 2 - .../ModbusRtuProtocalLinker.cs | 7 +- .../Modbus.Net.Modbus/ModbusTcpProtocal.cs | 3 +- .../ModbusTcpProtocalLinker.cs | 7 +- Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 94 +++-- .../Modbus.Net.OPC/AddressFormaterOpc.cs | 8 +- Modbus.Net/Modbus.Net.OPC/ClientExtend.cs | 8 +- .../Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs | 23 +- Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 40 +- Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs | 6 +- Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs | 9 +- .../Modbus.Net.OPC/OpcDaProtocalLinker.cs | 3 +- Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs | 5 +- Modbus.Net/Modbus.Net.OPC/OpcMachine.cs | 5 +- Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs | 8 +- .../Modbus.Net.OPC/OpcProtocalLinker.cs | 9 +- Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs | 10 +- Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs | 16 +- Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs | 8 +- .../Modbus.Net.OPC/OpcUaProtocalLinker.cs | 11 +- Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs | 10 +- Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 19 +- Modbus.Net/Modbus.Net.OPC/packages.config | 4 - .../AddressFormaterSiemens.cs | 16 +- .../AddressTranslatorSiemens.cs | 12 +- .../Modbus.Net.Siemens/SiemensPpiProtocal.cs | 12 +- .../SiemensPpiProtocalLinker.cs | 6 +- .../Modbus.Net.Siemens/SiemensProtocal.cs | 23 +- .../SiemensProtocalLinkerBytesExtend.cs | 4 +- .../Modbus.Net.Siemens/SiemensTcpProtocal.cs | 18 +- .../Modbus.Net.Siemens/SiemensUtility.cs | 6 +- Modbus.Net/Modbus.Net/App.config | 21 +- Modbus.Net/Modbus.Net/ComConnector.cs | 181 ++++++--- Modbus.Net/Modbus.Net/ComProtocalLinker.cs | 6 +- Modbus.Net/src/Base.Common/AddressCombiner.cs | 94 ++--- Modbus.Net/src/Base.Common/AddressHelper.cs | 12 +- .../src/Base.Common/AddressTranslator.cs | 8 +- Modbus.Net/src/Base.Common/AsyncHelper.cs | 2 +- Modbus.Net/src/Base.Common/BaseMachine.cs | 213 +++++----- .../src/Base.Common/BaseMachineExtend.cs | 2 +- Modbus.Net/src/Base.Common/BaseProtocal.cs | 122 +++--- Modbus.Net/src/Base.Common/BaseUtility.cs | 83 ++-- Modbus.Net/src/Base.Common/CRC16.cs | 31 +- Modbus.Net/src/Base.Common/IMachineMethod.cs | 4 - Modbus.Net/src/Base.Common/IProtocal.cs | 11 +- .../src/Base.Common/IProtocalFormatting.cs | 13 +- Modbus.Net/src/Base.Common/IProtocalLinker.cs | 8 +- .../Base.Common/IProtocalLinkerBytesExtend.cs | 1 - Modbus.Net/src/Base.Common/IUtilityMethod.cs | 19 +- Modbus.Net/src/Base.Common/ProtocalLinker.cs | 60 +-- Modbus.Net/src/Base.Common/ProtocalUnit.cs | 53 ++- Modbus.Net/src/Base.Common/TaskManager.cs | 128 +++--- Modbus.Net/src/Base.Common/TcpConnector.cs | 14 - .../src/Base.Common/TcpProtocalLinker.cs | 3 +- Modbus.Net/src/Base.Common/TypeExtensions.cs | 40 +- Modbus.Net/src/Base.Common/ValueHelper.cs | 46 +-- Samples/AnyType/AnyType.csproj | 91 ++--- Samples/AnyType/Content/bootstrap-theme.css | 384 ++++++++++++++++++ .../AnyType/Content/bootstrap-theme.min.css | 1 + Samples/AnyType/Content/bootstrap.css | 11 - Samples/AnyType/Content/bootstrap.min.css | 11 - Samples/AnyType/Scripts/_references.js | Bin 674 -> 339 bytes Samples/AnyType/Scripts/jquery-1.10.2.js | 14 - Samples/AnyType/Scripts/jquery-1.10.2.min.js | 17 - .../AnyType/Scripts/jquery.validate-vsdoc.js | 14 - Samples/AnyType/Scripts/jquery.validate.js | 14 - .../AnyType/Scripts/jquery.validate.min.js | 14 - Samples/AnyType/Scripts/respond.js | 14 - Samples/AnyType/Scripts/respond.min.js | 14 - Samples/CrossLamp/Content/bootstrap-theme.css | 384 ++++++++++++++++++ .../CrossLamp/Content/bootstrap-theme.min.css | 1 + Samples/CrossLamp/Content/bootstrap.css | 11 - Samples/CrossLamp/Content/bootstrap.min.css | 11 - Samples/CrossLamp/CrossLamp.csproj | 91 ++--- Samples/CrossLamp/Scripts/_references.js | Bin 676 -> 340 bytes Samples/CrossLamp/Scripts/jquery-1.10.2.js | 14 - .../CrossLamp/Scripts/jquery-1.10.2.min.js | 17 - .../Scripts/jquery.validate-vsdoc.js | 14 - Samples/CrossLamp/Scripts/jquery.validate.js | 14 - .../CrossLamp/Scripts/jquery.validate.min.js | 14 - Samples/CrossLamp/Scripts/respond.js | 14 - Samples/CrossLamp/Scripts/respond.min.js | 14 - .../TaskManager/Content/bootstrap-theme.css | 384 ++++++++++++++++++ .../Content/bootstrap-theme.min.css | 1 + Samples/TaskManager/Content/bootstrap.css | 11 - Samples/TaskManager/Content/bootstrap.min.css | 11 - Samples/TaskManager/Scripts/_references.js | Bin 674 -> 339 bytes Samples/TaskManager/Scripts/jquery-1.10.2.js | 14 - .../TaskManager/Scripts/jquery-1.10.2.min.js | 17 - .../Scripts/jquery.validate-vsdoc.js | 14 - .../TaskManager/Scripts/jquery.validate.js | 14 - .../Scripts/jquery.validate.min.js | 14 - Samples/TaskManager/Scripts/respond.js | 14 - Samples/TaskManager/Scripts/respond.min.js | 14 - Samples/TaskManager/TaskManager.csproj | 91 ++--- Samples/TripleAdd/Content/bootstrap-theme.css | 384 ++++++++++++++++++ .../TripleAdd/Content/bootstrap-theme.min.css | 1 + Samples/TripleAdd/Content/bootstrap.css | 11 - Samples/TripleAdd/Content/bootstrap.min.css | 11 - Samples/TripleAdd/Scripts/_references.js | Bin 788 -> 396 bytes Samples/TripleAdd/Scripts/jquery-1.10.2.js | 14 - .../TripleAdd/Scripts/jquery-1.10.2.min.js | 17 - .../Scripts/jquery.validate-vsdoc.js | 14 - Samples/TripleAdd/Scripts/jquery.validate.js | 14 - .../TripleAdd/Scripts/jquery.validate.min.js | 14 - Samples/TripleAdd/Scripts/respond.js | 14 - Samples/TripleAdd/Scripts/respond.min.js | 14 - Samples/TripleAdd/TripleAdd.csproj | 91 ++--- 113 files changed, 2490 insertions(+), 1557 deletions(-) delete mode 100644 Modbus.Net/Modbus.Net.OPC/packages.config create mode 100644 Samples/AnyType/Content/bootstrap-theme.css create mode 100644 Samples/AnyType/Content/bootstrap-theme.min.css create mode 100644 Samples/CrossLamp/Content/bootstrap-theme.css create mode 100644 Samples/CrossLamp/Content/bootstrap-theme.min.css create mode 100644 Samples/TaskManager/Content/bootstrap-theme.css create mode 100644 Samples/TaskManager/Content/bootstrap-theme.min.css create mode 100644 Samples/TripleAdd/Content/bootstrap-theme.css create mode 100644 Samples/TripleAdd/Content/bootstrap-theme.min.css diff --git a/Modbus.Net/Modbus.Net.Core/App.config b/Modbus.Net/Modbus.Net.Core/App.config index e85257a..8874465 100644 --- a/Modbus.Net/Modbus.Net.Core/App.config +++ b/Modbus.Net/Modbus.Net.Core/App.config @@ -1,13 +1,14 @@ - + + - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs index 9fb6291..09dd844 100644 --- a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs +++ b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs @@ -1,20 +1,39 @@ -using System.Collections.Generic; using System.IO; using Microsoft.Extensions.Configuration; namespace Modbus.Net { + /// + /// Simulate ConfigurationManager in System.Configuration + /// public static class ConfigurationManager { - private static IConfigurationBuilder builder = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) + /// + /// Configuration Builder + /// + private static readonly IConfigurationBuilder Builder = new ConfigurationBuilder() + .SetBasePath(RootPath ?? Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .AddXmlFile("App.config"); - private static IConfigurationRoot Configuration => builder.Build(); + /// + /// RootPath of App.config and appsettings.json + /// + public static string RootPath { get; set; } = null; + /// + /// Configuration Root + /// + private static IConfigurationRoot Configuration => Builder.Build(); + + /// + /// AppSettings + /// public static IConfigurationSection AppSettings => Configuration.GetSection("AppSettings"); + /// + /// ConnectionStrings + /// public static IConfigurationSection ConnectionStrings => Configuration.GetSection("ConnectionStrings"); } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs index 7822cf6..3edcd80 100644 --- a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs +++ b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs @@ -12,10 +12,12 @@ namespace Modbus.Net.Modbus /// 读功能码 /// protected Dictionary ReadFunctionCodeDictionary; + /// /// 功能码翻译至标准Modbus地址位置 /// protected Dictionary TransDictionary; + /// /// 写功能码 /// @@ -201,6 +203,7 @@ namespace Modbus.Net.Modbus /// 读功能码 /// protected Dictionary ReadFunctionCodeDictionary; + /// /// 写功能码 /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs index f314fca..a37c55a 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs @@ -8,7 +8,8 @@ namespace Modbus.Net.Modbus /// public class ModbusAsciiProtocalLinker : ComProtocalLinker { - public ModbusAsciiProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) + public ModbusAsciiProtocalLinker(string com, int slaveAddress) + : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { } @@ -18,14 +19,10 @@ namespace Modbus.Net.Modbus //CRC校验失败 var contentString = Encoding.ASCII.GetString(content); if (!Crc16.GetInstance().LrcEfficacy(contentString)) - { throw new ModbusProtocalErrorException(501); - } //Modbus协议错误 if (byte.Parse(contentString.Substring(3, 2)) > 127) - { throw new ModbusProtocalErrorException(byte.Parse(contentString.Substring(5, 2))); - } return true; } } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs index ccf49b5..f261609 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs @@ -47,7 +47,8 @@ namespace Modbus.Net.Modbus /// public abstract class ModbusProtocal : BaseProtocal { - protected ModbusProtocal(byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) + protected ModbusProtocal(byte slaveAddress, byte masterAddress, Endian endian) + : base(slaveAddress, masterAddress, endian) { } @@ -73,7 +74,8 @@ namespace Modbus.Net.Modbus var translateAddress = addressTranslator.AddressTranslate(startAddress, true); FunctionCode = (byte) translateAddress.Area; StartAddress = (ushort) translateAddress.Address; - GetCount = (ushort) Math.Ceiling(getCount/addressTranslator.GetAreaByteLength(translateAddress.AreaString)); + GetCount = + (ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); } public byte SlaveAddress { get; } @@ -140,7 +142,7 @@ namespace Modbus.Net.Modbus StartAddress = (ushort) translateAddress.Address; var writeByteValue = ValueHelper.GetInstance(endian).ObjectArrayToByteArray(writeValue); WriteCount = - (ushort) (writeByteValue.Length/addressTranslator.GetAreaByteLength(translateAddress.AreaString)); + (ushort) (writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); WriteByteCount = (byte) writeByteValue.Length; WriteValue = writeByteValue; } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs index b079c45..ae67594 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs @@ -61,9 +61,7 @@ namespace Modbus.Net.Modbus var newContent = new List(); newContent.AddRange(Encoding.ASCII.GetBytes(":")); foreach (var number in content) - { newContent.AddRange(Encoding.ASCII.GetBytes(number.ToString("X2"))); - } newContent.AddRange(Encoding.ASCII.GetBytes(Crc16.GetInstance().GetLRC(content))); newContent.Add(0x0d); newContent.Add(0x0a); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs index 0d91f6b..6fa4466 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs @@ -7,7 +7,8 @@ namespace Modbus.Net.Modbus /// public class ModbusRtuProtocalLinker : ComProtocalLinker { - public ModbusRtuProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) + public ModbusRtuProtocalLinker(string com, int slaveAddress) + : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { } @@ -16,14 +17,10 @@ namespace Modbus.Net.Modbus if (!base.CheckRight(content).Value) return false; //CRC校验失败 if (!Crc16.GetInstance().CrcEfficacy(content)) - { throw new ModbusProtocalErrorException(501); - } //Modbus协议错误 if (content[1] > 127) - { throw new ModbusProtocalErrorException(content[2]); - } return true; } } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs index d403e21..a15b339 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs @@ -12,7 +12,8 @@ namespace Modbus.Net.Modbus { } - public ModbusTcpProtocal(string ip, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) + public ModbusTcpProtocal(string ip, byte slaveAddress, byte masterAddress, Endian endian) + : base(slaveAddress, masterAddress, endian) { ProtocalLinker = new ModbusTcpProtocalLinker(ip); } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs index 87a8a22..f0cfe6e 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs @@ -7,7 +7,8 @@ namespace Modbus.Net.Modbus /// public class ModbusTcpProtocalLinker : TcpProtocalLinker { - public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"] ?? "502")) + public ModbusTcpProtocalLinker(string ip) + : base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"] ?? "502")) { } @@ -20,14 +21,10 @@ namespace Modbus.Net.Modbus if (!base.CheckRight(content).Value) return false; //长度校验失败 if (content[5] != content.Length - 6) - { throw new ModbusProtocalErrorException(500); - } //Modbus协议错误 if (content[7] > 127) - { throw new ModbusProtocalErrorException(content[2] > 0 ? content[2] : content[8]); - } return true; } } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index fac9f5b..5f6cbb2 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -27,14 +27,15 @@ namespace Modbus.Net.Modbus /// /// Modbus基础Api入口 /// - public class ModbusUtility : BaseUtility, IUtilityMethodTime + public class ModbusUtility : BaseUtility, IIUtilityMethodTime { /// /// Modbus协议类型 /// private ModbusType _modbusType; - public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) + public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress, + Endian endian = Endian.BigEndianLsb) : base(slaveAddress, masterAddress) { Endian = endian; @@ -43,7 +44,8 @@ namespace Modbus.Net.Modbus AddressTranslator = new AddressTranslatorModbus(); } - public ModbusUtility(ModbusType connectionType, string connectionString, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) + public ModbusUtility(ModbusType connectionType, string connectionString, byte slaveAddress, byte masterAddress, + Endian endian = Endian.BigEndianLsb) : base(slaveAddress, masterAddress) { Endian = endian; @@ -120,6 +122,47 @@ namespace Modbus.Net.Modbus } } + /// + /// 读时间 + /// + /// 设备的时间 + public async Task GetTimeAsync() + { + try + { + var inputStruct = new GetSystemTimeModbusInputStruct(SlaveAddress); + var outputStruct = + await Wrapper.SendReceiveAsync( + Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct); + return outputStruct?.Time ?? DateTime.MinValue; + } + catch (Exception) + { + return DateTime.MinValue; + } + } + + /// + /// 写时间 + /// + /// 需要写入的时间 + /// 写入是否成功 + public async Task SetTimeAsync(DateTime setTime) + { + try + { + var inputStruct = new SetSystemTimeModbusInputStruct(SlaveAddress, setTime); + var outputStruct = + await Wrapper.SendReceiveAsync( + Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct); + return outputStruct?.WriteCount > 0; + } + catch (Exception) + { + return false; + } + } + public override void SetConnectionType(int connectionType) { ModbusType = (ModbusType) connectionType; @@ -138,7 +181,8 @@ namespace Modbus.Net.Modbus var inputStruct = new ReadDataModbusInputStruct(SlaveAddress, startAddress, (ushort) getByteCount, AddressTranslator); var outputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct); + Wrapper.SendReceiveAsync(Wrapper[typeof(ReadDataModbusProtocal)], + inputStruct); return outputStruct?.DataValue; } catch @@ -160,7 +204,8 @@ namespace Modbus.Net.Modbus var inputStruct = new WriteDataModbusInputStruct(SlaveAddress, startAddress, setContents, AddressTranslator, Endian); var outputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof (WriteDataModbusProtocal)], inputStruct); + Wrapper.SendReceiveAsync(Wrapper[typeof(WriteDataModbusProtocal)], + inputStruct); return outputStruct?.WriteCount == setContents.Length; } catch @@ -168,44 +213,5 @@ namespace Modbus.Net.Modbus return false; } } - - /// - /// 读时间 - /// - /// 设备的时间 - public async Task GetTimeAsync() - { - try - { - var inputStruct = new GetSystemTimeModbusInputStruct(SlaveAddress); - var outputStruct = - await Wrapper.SendReceiveAsync(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct); - return outputStruct?.Time ?? DateTime.MinValue; - } - catch (Exception) - { - return DateTime.MinValue; - } - } - - /// - /// 写时间 - /// - /// 需要写入的时间 - /// 写入是否成功 - public async Task SetTimeAsync(DateTime setTime) - { - try - { - var inputStruct = new SetSystemTimeModbusInputStruct(SlaveAddress, setTime); - var outputStruct = - await Wrapper.SendReceiveAsync(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct); - return outputStruct?.WriteCount > 0; - } - catch (Exception) - { - return false; - } - } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs b/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs index a880837..2d9a4f6 100644 --- a/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs +++ b/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs @@ -6,7 +6,8 @@ namespace Modbus.Net.OPC /// /// Opc地址编码器 /// - public class AddressFormaterOpc : AddressFormater where TMachineKey : IEquatable where TUnitKey : IEquatable + public class AddressFormaterOpc : AddressFormater where TMachineKey : IEquatable + where TUnitKey : IEquatable { /// /// 协议构造器 @@ -14,7 +15,8 @@ namespace Modbus.Net.OPC /// 如何通过BaseMachine和AddressUnit构造Opc的标签 /// 调用这个编码器的设备 /// 每两个标签之间用什么符号隔开,默认为/ - public AddressFormaterOpc(Func, AddressUnit, string[]> tagGeter, BaseMachine machine, + public AddressFormaterOpc(Func, AddressUnit, string[]> tagGeter, + BaseMachine machine, char seperator = '/') { Machine = machine; @@ -35,9 +37,7 @@ namespace Modbus.Net.OPC var strings = TagGeter(Machine, findAddress); var ans = ""; for (var i = 0; i < strings.Length; i++) - { ans += strings[i].Trim().Replace(" ", "") + Seperator; - } ans = ans.Substring(0, ans.Length - 1); return ans; } diff --git a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs index 7539f34..d745f7a 100644 --- a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs +++ b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs @@ -1,16 +1,16 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Hylasoft.Opc.Common; using Hylasoft.Opc.Da; -using Opc; -using Opc.Da; -using System.Collections.Generic; using Hylasoft.Opc.Ua; namespace Modbus.Net.OPC { public interface IClientExtend : IDisposable { + Node RootNodeBase { get; } + void Connect(); T Read(string tag); @@ -24,8 +24,6 @@ namespace Modbus.Net.OPC Task FindNodeAsync(string tag); Task> ExploreFolderAsync(string tag); - - Node RootNodeBase { get; } } public class MyDaClient : DaClient, IClientExtend diff --git a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs index 991f80c..074d867 100644 --- a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs +++ b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs @@ -1,27 +1,20 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Configuration; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Modbus.Net.OPC.FBox { public class FBoxOpcDaMachine : OpcDaMachine { - public string LocalSequence { get; set; } - - public string LinkerName { get; set; } - public FBoxOpcDaMachine(string localSequence, string linkerName, - IEnumerable getAddresses, bool keepConnect) : base(ConfigurationManager.AppSettings["FBoxOpcDaHost"], getAddresses, keepConnect) + IEnumerable getAddresses, bool keepConnect) + : base(ConfigurationManager.AppSettings["FBoxOpcDaHost"], getAddresses, keepConnect) { LocalSequence = localSequence; LinkerName = linkerName; AddressFormater = - new AddressFormaterOpc( + new AddressFormaterOpc( (machine, unit) => - new string[] + new[] { "(.*)", ((FBoxOpcDaMachine) machine).LinkerName, ((FBoxOpcDaMachine) machine).LocalSequence, unit.Name @@ -33,5 +26,9 @@ namespace Modbus.Net.OPC.FBox : this(localSequence, linkerName, getAddresses, false) { } + + public string LocalSequence { get; set; } + + public string LinkerName { get; set; } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index 8c4eb6f..6c10bc7 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -1,25 +1,25 @@ -using Hylasoft.Opc.Common; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Hylasoft.Opc.Common; namespace Modbus.Net.OPC { public abstract class OpcConnector : BaseConnector { - protected IClientExtend Client; - protected bool _connect; - public override string ConnectionToken { get; } - public override bool IsConnected => _connect; + protected IClientExtend Client; protected OpcConnector(string host) { ConnectionToken = host; - } + } + + public override string ConnectionToken { get; } + public override bool IsConnected => _connect; public override bool Disconnect() { @@ -56,15 +56,12 @@ namespace Modbus.Net.OPC private void FoldWith(List tagSplitList, char splitChar, char startChar, char endChar) { - for (int i = 0; i < tagSplitList.Count; i++) - { - if (tagSplitList[i].Count(ch=>ch == startChar) > tagSplitList[i].Count(ch=>ch == endChar)) - { - for (int j = i + 1; j < tagSplitList.Count; j++) - { + for (var i = 0; i < tagSplitList.Count; i++) + if (tagSplitList[i].Count(ch => ch == startChar) > tagSplitList[i].Count(ch => ch == endChar)) + for (var j = i + 1; j < tagSplitList.Count; j++) if (tagSplitList[j].Contains(endChar)) { - for (int k = i + 1; k <= j; k++) + for (var k = i + 1; k <= j; k++) { tagSplitList[i] += splitChar + tagSplitList[i + 1]; tagSplitList.RemoveAt(i + 1); @@ -72,9 +69,6 @@ namespace Modbus.Net.OPC i--; break; } - } - } - } } private string[] SplitTag(string tag, char split) @@ -108,7 +102,7 @@ namespace Modbus.Net.OPC Value = BigEndianValueHelper.Instance.GetBytes(result, result.GetType()) }; } - return new OpcParamOut() + return new OpcParamOut { Success = false, Value = Encoding.ASCII.GetBytes("NoData") @@ -132,17 +126,17 @@ namespace Modbus.Net.OPC catch (Exception e) { AddInfo("opc write exception:" + e.Message); - return new OpcParamOut() + return new OpcParamOut { Success = false }; } - return new OpcParamOut() + return new OpcParamOut { Success = true }; } - return new OpcParamOut() + return new OpcParamOut { Success = false }; @@ -151,7 +145,7 @@ namespace Modbus.Net.OPC catch (Exception e) { AddInfo("opc client exception:" + e.Message); - return new OpcParamOut() + return new OpcParamOut { Success = false, Value = Encoding.ASCII.GetBytes("NoData") @@ -203,4 +197,4 @@ namespace Modbus.Net.OPC return Task.FromResult(Connect()); } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs index 1beddcb..4813ef2 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs @@ -1,9 +1,5 @@ -using Hylasoft.Opc.Common; -using System; +using System; using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; namespace Modbus.Net.OPC { diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs index ef5eeec..681fee1 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs @@ -3,7 +3,8 @@ using System.Collections.Generic; namespace Modbus.Net.OPC { - public class OpcDaMachine : OpcMachine where TKey : IEquatable where TUnitKey : IEquatable + public class OpcDaMachine : OpcMachine where TKey : IEquatable + where TUnitKey : IEquatable { public OpcDaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect) : base(getAddresses, keepConnect) @@ -21,12 +22,12 @@ namespace Modbus.Net.OPC public class OpcDaMachine : OpcMachine { - public OpcDaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect) + public OpcDaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { BaseUtility = new OpcDaUtility(connectionString); - ((OpcUtility)BaseUtility).GetSeperator += - () => ((AddressFormaterOpc)AddressFormater).Seperator; + ((OpcUtility) BaseUtility).GetSeperator += + () => ((AddressFormaterOpc) AddressFormater).Seperator; } public OpcDaMachine(string connectionString, IEnumerable getAddresses) diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs index f65da98..c98b617 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs @@ -1,10 +1,9 @@ using System.Configuration; -using System.Text; namespace Modbus.Net.OPC { /// - /// Opc Da协议连接器 + /// Opc Da协议连接器 /// public class OpcDaProtocalLinker : OpcProtocalLinker { diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs index f59ee5c..d52232d 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs @@ -1,7 +1,4 @@ -using System; -using System.Threading.Tasks; - -namespace Modbus.Net.OPC +namespace Modbus.Net.OPC { /// /// Opc Da协议Api入口 diff --git a/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs index 034508b..3803e54 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Modbus.Net.OPC { @@ -32,4 +29,4 @@ namespace Modbus.Net.OPC AddressCombinerSet = new AddressCombinerSingle(); } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs index 119b088..6f48d67 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs @@ -1,6 +1,4 @@ -using System.Text; - -namespace Modbus.Net.OPC +namespace Modbus.Net.OPC { /// /// Opc协议 @@ -41,7 +39,7 @@ namespace Modbus.Net.OPC public override OpcParamIn Format(IInputStruct message) { var r_message = (ReadRequestOpcInputStruct) message; - return new OpcParamIn() + return new OpcParamIn { IsRead = true, Tag = r_message.Tag, @@ -88,7 +86,7 @@ namespace Modbus.Net.OPC public override OpcParamIn Format(IInputStruct message) { var r_message = (WriteRequestOpcInputStruct) message; - return new OpcParamIn() + return new OpcParamIn { IsRead = false, Tag = r_message.Tag, diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs index c042357..d76b2cf 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Text; using System.Threading.Tasks; namespace Modbus.Net.OPC @@ -51,10 +48,8 @@ namespace Modbus.Net.OPC { if (content == null || !content.Success) return false; if (content.Value.Length == 6 && Encoding.ASCII.GetString(content.Value) == "NoData") - { return null; - } return base.CheckRight(content); } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs index 8636986..8fc4152 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs @@ -1,11 +1,5 @@ -using Hylasoft.Opc.Common; -using Hylasoft.Opc.Ua; -using System; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; namespace Modbus.Net.OPC { @@ -31,4 +25,4 @@ namespace Modbus.Net.OPC return _instances[host]; } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs index 92b00dd..7e49287 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs @@ -1,19 +1,17 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Modbus.Net.OPC { - public class OpcUaMachine : OpcMachine where TKey : IEquatable where TUnitKey : IEquatable + public class OpcUaMachine : OpcMachine where TKey : IEquatable + where TUnitKey : IEquatable { public OpcUaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { BaseUtility = new OpcUaUtility(connectionString); - ((OpcUtility)BaseUtility).GetSeperator += - () => ((AddressFormaterOpc)AddressFormater).Seperator; + ((OpcUtility) BaseUtility).GetSeperator += + () => ((AddressFormaterOpc) AddressFormater).Seperator; } public OpcUaMachine(string connectionString, IEnumerable> getAddresses) @@ -28,8 +26,8 @@ namespace Modbus.Net.OPC : base(getAddresses, keepConnect) { BaseUtility = new OpcUaUtility(connectionString); - ((OpcUtility)BaseUtility).GetSeperator += - () => ((AddressFormaterOpc)AddressFormater).Seperator; + ((OpcUtility) BaseUtility).GetSeperator += + () => ((AddressFormaterOpc) AddressFormater).Seperator; } public OpcUaMachine(string connectionString, IEnumerable getAddresses) @@ -37,4 +35,4 @@ namespace Modbus.Net.OPC { } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs index 762d487..b146880 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Modbus.Net.OPC { @@ -33,4 +29,4 @@ namespace Modbus.Net.OPC return true; } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs index 8048b97..31b3279 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Configuration; namespace Modbus.Net.OPC { /// - /// Opc Da协议连接器 + /// Opc Da协议连接器 /// public class OpcUaProtocalLinker : OpcProtocalLinker { @@ -21,4 +16,4 @@ namespace Modbus.Net.OPC BaseConnector = OpcUaConnector.Instance(host); } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs index 6502f2a..e061c28 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Modbus.Net.OPC +namespace Modbus.Net.OPC { /// /// Opc Da协议Api入口 @@ -16,4 +10,4 @@ namespace Modbus.Net.OPC Wrapper = new OpcUaProtocal(ConnectionString); } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index 50ce8a5..5b8f454 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -1,25 +1,22 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Modbus.Net.OPC { public abstract class OpcUtility : BaseUtility> - { + { + public delegate char GetSeperatorDelegate(); + protected OpcUtility(string connectionString) : base(0, 0) { ConnectionString = connectionString; AddressTranslator = new AddressTranslatorOpc(); } - public delegate char GetSeperatorDelegate(); + public override Endian Endian => Endian.BigEndianLsb; public event GetSeperatorDelegate GetSeperator; - public override Endian Endian => Endian.BigEndianLsb; - public override void SetConnectionType(int connectionType) { throw new NotImplementedException(); @@ -33,7 +30,8 @@ namespace Modbus.Net.OPC var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, split); var readRequestOpcOutputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct); + Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], + readRequestOpcInputStruct); return readRequestOpcOutputStruct?.GetValue; } catch (Exception) @@ -50,7 +48,8 @@ namespace Modbus.Net.OPC var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, split, setContents[0]); var writeRequestOpcOutputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestOpcProtocal)], writeRequestOpcInputStruct); + Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestOpcProtocal)], + writeRequestOpcInputStruct); return writeRequestOpcOutputStruct?.WriteResult == true; } catch (Exception e) @@ -59,4 +58,4 @@ namespace Modbus.Net.OPC } } } -} +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/packages.config b/Modbus.Net/Modbus.Net.OPC/packages.config deleted file mode 100644 index 1b83f0e..0000000 --- a/Modbus.Net/Modbus.Net.OPC/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs b/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs index da96bb5..923e4c1 100644 --- a/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs +++ b/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs @@ -17,7 +17,7 @@ } /// - /// Siemens地址格式化(Siemens格式) + /// Siemens地址格式化(Siemens格式) /// public class AddressFormaterSimenseStandard : AddressFormater { @@ -25,26 +25,16 @@ { if (area.Length > 1 && area.ToUpper().Substring(0, 2) == "DB") - { return area.ToUpper() + "." + "DB" + address; - } - else - { - return area.ToUpper() + address; - } + return area.ToUpper() + address; } public override string FormatAddress(string area, int address, int subAddress) { if (area.Length > 1 && area.ToUpper().Substring(0, 2) == "DB") - { return area.ToUpper() + "." + "DB" + address + "." + subAddress; - } - else - { - return area.ToUpper() + address + "." + subAddress; - } + return area.ToUpper() + address + "." + subAddress; } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs index f1f59ea..b19dbb2 100644 --- a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs +++ b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs @@ -53,7 +53,7 @@ namespace Modbus.Net.Siemens return new AddressDef { AreaString = "DB" + head, - Area = int.Parse(head)*256 + AreaCodeDictionary["DB"], + Area = int.Parse(head) * 256 + AreaCodeDictionary["DB"], Address = int.Parse(tail), SubAddress = int.Parse(sub) }; @@ -96,7 +96,7 @@ namespace Modbus.Net.Siemens {"Q", 0x82}, {"M", 0x83}, {"DB", 0x84}, - {"V", 0x184}, + {"V", 0x184} }; } @@ -118,15 +118,13 @@ namespace Modbus.Net.Siemens SubAddress = addressSplit.Length == 2 ? 0 : int.Parse(addressSplit[2]) }; } - int i = 0; + var i = 0; int t; while (!int.TryParse(address[i].ToString(), out t) && i < address.Length) - { i++; - } if (i == 0 || i >= address.Length) throw new FormatException(); - string head = address.Substring(0, i); - string[] tail = address.Substring(i).Split('.'); + var head = address.Substring(0, i); + var tail = address.Substring(i).Split('.'); return new AddressDef { AreaString = head, diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs index d91aa63..a14fc97 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs @@ -29,9 +29,7 @@ namespace Modbus.Net.Siemens public override async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) - { await ConnectAsync(); - } return await base.SendReceiveAsync(Endian, content); } @@ -51,17 +49,17 @@ namespace Modbus.Net.Siemens var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress); var outputStruct = await await - ForceSendReceiveAsync(this[typeof (ComCreateReferenceSiemensProtocal)], - inputStruct). + ForceSendReceiveAsync(this[typeof(ComCreateReferenceSiemensProtocal)], + inputStruct). ContinueWith(async answer => { if (!ProtocalLinker.IsConnected) return false; var inputStruct2 = new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress); var outputStruct2 = (ComConfirmMessageSiemensOutputStruct) - await - ForceSendReceiveAsync(this[typeof (ComConfirmMessageSiemensProtocal)], - inputStruct2); + await + ForceSendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocal)], + inputStruct2); return outputStruct2 != null; }); return outputStruct; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs index b8d93f1..6c8c0e0 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs @@ -65,15 +65,11 @@ namespace Modbus.Net.Siemens if (!base.CheckRight(content).Value) return false; var fcsCheck = 0; if (content.Length == 1 && content[0] == 0xe5) - { return true; - } if (content.Length == 6 && content[3] == 0) return true; for (var i = 4; i < content.Length - 2; i++) - { fcsCheck += content[i]; - } - fcsCheck = fcsCheck%256; + fcsCheck = fcsCheck % 256; if (fcsCheck != content[content.Length - 2]) return false; if (content[content.Length - 1] != 0x16) return false; if (content[1] != content.Length - 6) return false; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs index df178d5..588e15c 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs @@ -104,7 +104,8 @@ namespace Modbus.Net.Siemens public abstract class SiemensProtocal : BaseProtocal { - protected SiemensProtocal(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress, Endian.BigEndianLsb) + protected SiemensProtocal(byte slaveAddress, byte masterAddress) + : base(slaveAddress, masterAddress, Endian.BigEndianLsb) { } } @@ -142,7 +143,7 @@ namespace Modbus.Net.Siemens public override byte[] Format(IInputStruct message) { var r_message = (ComCreateReferenceSiemensInputStruct) message; - var crc = (r_message.SlaveAddress + r_message.MasterAddress + 0x49)%256; + var crc = (r_message.SlaveAddress + r_message.MasterAddress + 0x49) % 256; return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x49, (byte) crc, (byte) 0x16); } @@ -274,7 +275,7 @@ namespace Modbus.Net.Siemens public override byte[] Format(IInputStruct message) { var r_message = (ComConfirmMessageSiemensInputStruct) message; - var crc = r_message.SlaveAddress + r_message.MasterAddress + 0x5c%256; + var crc = r_message.SlaveAddress + r_message.MasterAddress + 0x5c % 256; return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x5c, (byte) crc, (byte) 0x16); } @@ -370,8 +371,8 @@ namespace Modbus.Net.Siemens var address = addressTranslator.AddressTranslate(startAddress, true); Offset = address.Address; var area = address.Area; - Area = (byte) (area%256); - DbBlock = Area == 0x84 ? (ushort) (area/256) : (ushort) 0; + Area = (byte) (area % 256); + DbBlock = Area == 0x84 ? (ushort) (area / 256) : (ushort) 0; NumberOfElements = getCount; } @@ -426,7 +427,7 @@ namespace Modbus.Net.Siemens var numberOfElements = r_message.NumberOfElements; var dbBlock = r_message.DbBlock; var area = r_message.Area; - var offsetBit = r_message.Offset*8; + var offsetBit = r_message.Offset * 8; var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit); return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x6c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables @@ -442,7 +443,7 @@ namespace Modbus.Net.Siemens var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); var dataType = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); var length = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); - var byteLength = length/8; + var byteLength = length / 8; var values = new byte[byteLength]; Array.Copy(messageBytes, pos, values, 0, byteLength); return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult, @@ -465,8 +466,8 @@ namespace Modbus.Net.Siemens var address = addressTranslator.AddressTranslate(startAddress, true); Offset = address.Address; var area = address.Area; - Area = (byte) (area%256); - DbBlock = Area == 0x84 ? (ushort) (area/256) : (ushort) 0; + Area = (byte) (area % 256); + DbBlock = Area == 0x84 ? (ushort) (area / 256) : (ushort) 0; WriteValue = writeValue; } @@ -514,11 +515,11 @@ namespace Modbus.Net.Siemens var numberOfElements = (ushort) valueBytes.Length; var dbBlock = r_message.DbBlock; var area = r_message.Area; - var offsetBit = r_message.Offset*8; + var offsetBit = r_message.Offset * 8; var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit); const byte reserved = 0x00; const byte type = (byte) SiemensDataType.OtherAccess; - var numberOfWriteBits = (ushort) (valueBytes.Length*8); + var numberOfWriteBits = (ushort) (valueBytes.Length * 8); return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x7c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables , variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area, diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs index 180c244..64af6bd 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs @@ -35,10 +35,8 @@ namespace Modbus.Net.Siemens 0, 4); var check = 0; for (var i = 4; i < newContent.Length - 2; i++) - { check += newContent[i]; - } - check = check%256; + check = check % 256; newContent[newContent.Length - 2] = (byte) check; newContent[newContent.Length - 1] = 0x16; return newContent; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs index 3150fa6..fc1d577 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs @@ -19,12 +19,16 @@ namespace Modbus.Net.Siemens 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.AppSettings["IP"]) + ushort maxPdu) + : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.AppSettings["IP"]) { } public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, - ushort maxPdu, string ip) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"])) + ushort maxPdu, string ip) + : this( + tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ip, + int.Parse(ConfigurationManager.AppSettings["SiemensPort"] ?? "102")) { } @@ -50,9 +54,7 @@ namespace Modbus.Net.Siemens public override async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) - { await ConnectAsync(); - } return await base.SendReceiveAsync(Endian, content); } @@ -92,7 +94,7 @@ namespace Modbus.Net.Siemens return //先建立连接,然后建立设备的引用 await await - ForceSendReceiveAsync(this[typeof (CreateReferenceSiemensProtocal)], inputStruct) + ForceSendReceiveAsync(this[typeof(CreateReferenceSiemensProtocal)], inputStruct) .ContinueWith(async answer => { if (!ProtocalLinker.IsConnected) return false; @@ -101,9 +103,9 @@ namespace Modbus.Net.Siemens _maxPdu); var outputStruct2 = (EstablishAssociationSiemensOutputStruct) - await - SendReceiveAsync(this[typeof (EstablishAssociationSiemensProtocal)], - inputStruct2); + 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 84cab37..4d81d49 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs @@ -183,7 +183,8 @@ namespace Modbus.Net.Siemens 0xd3c7, SiemensTypeCode.Byte, startAddress, (ushort) getByteCount, AddressTranslator); var readRequestSiemensOutputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)], + Wrapper.SendReceiveAsync( + Wrapper[typeof(ReadRequestSiemensProtocal)], readRequestSiemensInputStruct); return readRequestSiemensOutputStruct?.GetValue; } @@ -207,7 +208,8 @@ namespace Modbus.Net.Siemens 0xd3c8, startAddress, setContents, AddressTranslator); var writeRequestSiemensOutputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof (WriteRequestSiemensProtocal)], + Wrapper.SendReceiveAsync( + Wrapper[typeof(WriteRequestSiemensProtocal)], writeRequestSiemensInputStruct); return writeRequestSiemensOutputStruct?.AccessResult == SiemensAccessResult.NoError; } diff --git a/Modbus.Net/Modbus.Net/App.config b/Modbus.Net/Modbus.Net/App.config index 46b488f..44dba52 100644 --- a/Modbus.Net/Modbus.Net/App.config +++ b/Modbus.Net/Modbus.Net/App.config @@ -1,14 +1,15 @@ - + + - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs index 257289f..7802356 100644 --- a/Modbus.Net/Modbus.Net/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/ComConnector.cs @@ -9,8 +9,14 @@ using System.Threading.Tasks; namespace Modbus.Net { + /// + /// 具有发送锁的串口 + /// public class SerialPortLock : SerialPort { + /// + /// 发送锁 + /// public object Lock { get; set; } = new object(); } @@ -19,42 +25,87 @@ namespace Modbus.Net /// public class ComConnector : BaseConnector, IDisposable { - public delegate byte[] GetDate(byte[] bts); - - private static Dictionary Connectors { get; } = new Dictionary(); - private static Dictionary Linkers { get; } = new Dictionary(); - + /// + /// 波特率 + /// private readonly int _baudRate; - //private GetDate mygetDate; + /// + /// 串口地址 + /// private readonly string _com; + + /// + /// 数据位 + /// private readonly int _dataBits; + + /// + /// 奇偶校验 + /// private readonly Parity _parity; - private readonly StopBits _stopBits; - private readonly int _timeoutTime; + + /// + /// 从站号 + /// private readonly string _slave; - private bool m_disposed = false; + /// + /// 停止位 + /// + private readonly StopBits _stopBits; + /// + /// 超时时间 + /// + private readonly int _timeoutTime; + + /// + /// Dispose是否执行 + /// + private bool m_disposed; + + /// + /// 构造器 + /// + /// 串口地址:从站号 + /// 波特率 + /// 校验位 + /// 停止位 + /// 数据位 + /// 超时时间 public ComConnector(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int timeoutTime) { - _com = com.Split(':')[0]; - _timeoutTime = timeoutTime; - _baudRate = baudRate; - _parity = parity; - _stopBits = stopBits; - _dataBits = dataBits; - _slave = com.Split(':')[1]; - //端口号 + _com = com.Split(':')[0]; //读超时 - //比特率 - //奇偶校验 + _timeoutTime = timeoutTime; + //波特率 + _baudRate = baudRate; + //奇偶校验 + _parity = parity; //停止位 + _stopBits = stopBits; //数据位 - //从站号标识 + _dataBits = dataBits; + //从站号 + _slave = com.Split(':')[1]; } + /// + /// 连接中的串口 + /// + private static Dictionary Connectors { get; } = new Dictionary() + ; + + /// + /// 连接中的连接器 + /// + private static Dictionary Linkers { get; } = new Dictionary(); + + /// + /// 连接关键字(串口号:从站号) + /// public override string ConnectionToken => _slave + ":" + _com; private SerialPortLock SerialPort @@ -72,7 +123,7 @@ namespace Modbus.Net /// public void Dispose() { - Dispose(true); + Dispose(true); //.NET Framework 类库 // GC..::.SuppressFinalize 方法 //请求系统不要调用指定对象的终结器。 @@ -117,7 +168,9 @@ namespace Modbus.Net } else if (nReadLen == 0) + { nBytelen += 1; + } } } catch (Exception ex) @@ -146,7 +199,6 @@ namespace Modbus.Net SerialPort.ReadTimeout = ByteTime; while (nBytelen < ReadRoom - 1 && SerialPort.BytesToRead > 0) - { try { ReadBuf[nBytelen] = (byte) SerialPort.ReadByte(); @@ -156,7 +208,6 @@ namespace Modbus.Net { throw new Exception(ex.Message); } - } ReadBuf[nBytelen] = 0x00; return nBytelen; } @@ -171,9 +222,7 @@ namespace Modbus.Net { var StringOut = ""; foreach (var InByte in InBytes) - { StringOut = StringOut + string.Format("{0:X2}", InByte) + " "; - } return StringOut.Trim(); } @@ -190,9 +239,7 @@ namespace Modbus.Net byte[] ByteOut; ByteOut = new byte[ByteStrings.Length]; for (var i = 0; i <= ByteStrings.Length - 1; i++) - { ByteOut[i] = byte.Parse(ByteStrings[i], NumberStyles.HexNumber); - } return ByteOut; } @@ -207,7 +254,7 @@ namespace Modbus.Net InString = InString.Replace(" ", ""); try { - var ByteStrings = new string[InString.Length/2]; + var ByteStrings = new string[InString.Length / 2]; var j = 0; for (var i = 0; i < ByteStrings.Length; i++) { @@ -217,9 +264,7 @@ namespace Modbus.Net ByteOut = new byte[ByteStrings.Length]; for (var i = 0; i <= ByteStrings.Length - 1; i++) - { ByteOut[i] = byte.Parse(ByteStrings[i], NumberStyles.HexNumber); - } } catch (Exception ex) { @@ -285,24 +330,28 @@ namespace Modbus.Net #region 发送接收数据 + /// + /// 是否正在连接 + /// public override bool IsConnected { get { if (SerialPort != null && !SerialPort.IsOpen) - { SerialPort.Dispose(); - } return SerialPort != null && SerialPort.IsOpen && Linkers.ContainsKey(_slave); } } + /// + /// 连接串口 + /// + /// 是否连接成功 public override bool Connect() { try { if (!Connectors.ContainsKey(_com)) - { Connectors.Add(_com, new SerialPortLock { PortName = _com, @@ -312,29 +361,33 @@ namespace Modbus.Net DataBits = _dataBits, ReadTimeout = _timeoutTime }); - } if (!Linkers.ContainsKey(_slave)) - { Linkers.Add(_slave, _com); - } SerialPort.Open(); return true; } - catch (Exception e) + catch (Exception) { return false; } } + /// + /// 连接串口 + /// + /// 是否连接成功 public override Task ConnectAsync() { return Task.FromResult(Connect()); } + /// + /// 断开串口 + /// + /// 是否断开成功 public override bool Disconnect() { if (Linkers.ContainsKey(_slave) && Connectors.ContainsKey(_com)) - { try { Dispose(); @@ -344,28 +397,43 @@ namespace Modbus.Net { return false; } - } return false; } - public void SendMsg(string senStr) + /// + /// 带返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 + public string SendMsg(string sendStr) { - var myByte = StringToByte_2(senStr); + var myByte = StringToByte_2(sendStr); - SendMsg(myByte); + var returnBytes = SendMsg(myByte); + + return ByteToString(returnBytes); } + /// + /// 无返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override Task SendMsgWithoutReturnAsync(byte[] message) { return Task.FromResult(SendMsgWithoutReturn(message)); } + /// + /// 带返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override byte[] SendMsg(byte[] sendbytes) { try { if (!SerialPort.IsOpen) - { try { SerialPort.Open(); @@ -375,7 +443,6 @@ namespace Modbus.Net Dispose(); SerialPort.Open(); } - } lock (SerialPort.Lock) { SerialPort.Write(sendbytes, 0, sendbytes.Length); @@ -389,17 +456,26 @@ namespace Modbus.Net } } + /// + /// 带返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override Task SendMsgAsync(byte[] message) { return Task.FromResult(SendMsg(message)); } + /// + /// 无返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override bool SendMsgWithoutReturn(byte[] sendbytes) { try { if (!SerialPort.IsOpen) - { try { SerialPort.Open(); @@ -409,7 +485,6 @@ namespace Modbus.Net Dispose(); SerialPort.Open(); } - } lock (SerialPort.Lock) { SerialPort.Write(sendbytes, 0, sendbytes.Length); @@ -422,24 +497,12 @@ namespace Modbus.Net } } - public string ReadMsgStr() - { - var rd = ""; - - var data = ReadMsg(); - - rd = ByteToString(data); - return rd; - } - - public byte[] ReadMsg() + private byte[] ReadMsg() { try { if (!SerialPort.IsOpen) - { SerialPort.Open(); - } byte[] data; Thread.Sleep(100); diff --git a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs index 13d4461..98c7c89 100644 --- a/Modbus.Net/Modbus.Net/ComProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net/ComProtocalLinker.cs @@ -15,6 +15,7 @@ namespace Modbus.Net /// 校验位 /// 停止位 /// 数据位 + /// 从站地址 protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits, int slaveAddress) : this(ConfigurationManager.AppSettings["COM"], baudRate, parity, stopBits, dataBits, slaveAddress) { @@ -28,6 +29,7 @@ namespace Modbus.Net /// 校验位 /// 停止位 /// 数据位 + /// 从站地址 protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int slaveAddress) : this( @@ -45,10 +47,12 @@ namespace Modbus.Net /// 停止位 /// 数据位 /// 超时时间 + /// 从站地址 protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int connectionTimeout, int slaveAddress) { - BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, connectionTimeout); + BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate, parity, stopBits, dataBits, + connectionTimeout); } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/AddressCombiner.cs b/Modbus.Net/src/Base.Common/AddressCombiner.cs index 4ad03d5..305fb93 100644 --- a/Modbus.Net/src/Base.Common/AddressCombiner.cs +++ b/Modbus.Net/src/Base.Common/AddressCombiner.cs @@ -34,7 +34,8 @@ namespace Modbus.Net /// /// 地址转换器 /// 单个发送协议允许的数据最长长度(字节) - public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) : base(addressTranslator, maxLength) + public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) + : base(addressTranslator, maxLength) { } } @@ -44,11 +45,6 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombiner where TKey : IEquatable { - /// - /// 协议的数据最长长度(字节) - /// - protected int MaxLength { get; set; } - /// /// 构造函数 /// @@ -60,6 +56,11 @@ namespace Modbus.Net MaxLength = maxLength; } + /// + /// 协议的数据最长长度(字节) + /// + protected int MaxLength { get; set; } + /// /// 地址转换器 /// @@ -75,8 +76,8 @@ namespace Modbus.Net //按从小到大的顺序对地址进行排序 var groupedAddresses = from address in addresses orderby - AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, - AddressTranslator.GetAreaByteLength(address.Area)) + AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, + AddressTranslator.GetAreaByteLength(address.Area)) group address by address.Area into grouped select grouped; @@ -111,7 +112,7 @@ namespace Modbus.Net { //如果当前地址小于已经记录的地址域,表示这个地址的开始已经记录过了 if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, - AddressTranslator.GetAreaByteLength(address.Area)) < + AddressTranslator.GetAreaByteLength(address.Area)) < AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) @@ -119,20 +120,18 @@ namespace Modbus.Net originalAddresses.Add(address); //如果当前地址的末尾被记录,表示地址被记录的地址域覆盖,这个地址没有记录的必要 if (AddressHelper.GetProtocalCoordinateNextPosition( - AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, - AddressTranslator.GetAreaByteLength(address.Area)), - address.DataType, - AddressTranslator.GetAreaByteLength(address.Area)) <= + AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, + AddressTranslator.GetAreaByteLength(address.Area)), + address.DataType, + AddressTranslator.GetAreaByteLength(address.Area)) <= AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) - { continue; - } } //如果当前地址大于记录的地址域的开头,则表示地址已经不连续了 else if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, - AddressTranslator.GetAreaByteLength(address.Area)) > + AddressTranslator.GetAreaByteLength(address.Area)) > AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) @@ -144,12 +143,12 @@ namespace Modbus.Net Address = (int) Math.Floor(initNum), GetCount = (int) - Math.Ceiling( - AddressHelper.MapProtocalGetCountToAbstractByteCount( - preNum - (int) Math.Floor(initNum), - AddressTranslator.GetAreaByteLength(address.Area), - BigEndianValueHelper.Instance.ByteLength[preType.FullName])), - DataType = typeof (byte), + Math.Ceiling( + AddressHelper.MapProtocalGetCountToAbstractByteCount( + preNum - (int) Math.Floor(initNum), + AddressTranslator.GetAreaByteLength(address.Area), + BigEndianValueHelper.Instance.ByteLength[preType.FullName])), + DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() }); initNum = address.Address; @@ -174,24 +173,25 @@ namespace Modbus.Net Address = (int) Math.Floor(initNum), GetCount = (int) - Math.Ceiling( - AddressHelper.MapProtocalGetCountToAbstractByteCount( - preNum - (int) Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), - BigEndianValueHelper.Instance.ByteLength[preType.FullName])), - DataType = typeof (byte), + Math.Ceiling( + AddressHelper.MapProtocalGetCountToAbstractByteCount( + preNum - (int) Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), + BigEndianValueHelper.Instance.ByteLength[preType.FullName])), + DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() }); } - List> newAns = new List>(); + var newAns = new List>(); foreach (var communicationUnit in ans) { - double oldByteCount = communicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]; + var oldByteCount = communicationUnit.GetCount * + BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]; while (oldByteCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName] > MaxLength) { var newOriginalAddresses = new List>(); var oldOriginalAddresses = communicationUnit.OriginalAddresses.ToList(); - var newByteCount = 0.0; + var newByteCount = 0.0; do { var currentAddressUnit = oldOriginalAddresses.First(); @@ -200,7 +200,6 @@ namespace Modbus.Net oldByteCount -= BigEndianValueHelper.Instance.ByteLength[currentAddressUnit.DataType.FullName]; newOriginalAddresses.Add(currentAddressUnit); oldOriginalAddresses.RemoveAt(0); - } while (newByteCount < MaxLength); var newCommunicationUnit = new CommunicationUnit { @@ -212,9 +211,9 @@ namespace Modbus.Net (int) Math.Ceiling(newByteCount / BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]), - OriginalAddresses = newOriginalAddresses, + OriginalAddresses = newOriginalAddresses }; - + newAns.Add(newCommunicationUnit); } communicationUnit.GetCount = @@ -334,12 +333,12 @@ namespace Modbus.Net EndUnit = continusAddress, GapNumber = (int) - Math.Ceiling(AddressHelper.MapProtocalCoordinateToAbstractCoordinate( - continusAddress.Address, preCommunicationUnit.Address, - AddressTranslator.GetAreaByteLength(continusAddress.Area)) - - preCommunicationUnit.GetCount* - BigEndianValueHelper.Instance.ByteLength[ - preCommunicationUnit.DataType.FullName]) + Math.Ceiling(AddressHelper.MapProtocalCoordinateToAbstractCoordinate( + continusAddress.Address, preCommunicationUnit.Address, + AddressTranslator.GetAreaByteLength(continusAddress.Area)) - + preCommunicationUnit.GetCount * + BigEndianValueHelper.Instance.ByteLength[ + preCommunicationUnit.DataType.FullName]) }; addressesGaps.Add(gap); } @@ -350,12 +349,14 @@ namespace Modbus.Net var jumpNumberInner = JumpNumber; foreach (var orderedGap in orderedGaps) { - if (orderedGap.GapNumber <= 0) continue; + if (orderedGap.GapNumber <= 0) continue; var nowAddress = orderedGap.EndUnit; var index = continusAddresses.IndexOf(nowAddress); index--; var preAddress = continusAddresses[index]; - if (nowAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName] + preAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName] + orderedGap.GapNumber > MaxLength) continue; + if (nowAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName] + + preAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName] + + orderedGap.GapNumber > MaxLength) continue; jumpNumberInner -= orderedGap.GapNumber; if (jumpNumberInner < 0) break; continusAddresses.RemoveAt(index); @@ -367,11 +368,11 @@ namespace Modbus.Net Address = preAddress.Address, GetCount = (int) - (preAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName]) + + (preAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName]) + orderedGap.GapNumber + (int) - (nowAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName]), - DataType = typeof (byte), + (nowAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName]), + DataType = typeof(byte), OriginalAddresses = preAddress.OriginalAddresses.ToList().Union(nowAddress.OriginalAddresses) }; continusAddresses.Insert(index, newAddress); @@ -430,8 +431,9 @@ namespace Modbus.Net var addressUnits = addresses as IList> ?? addresses.ToList(); var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]); return - new AddressCombinerNumericJump((int) (count*Percentage/100.0), MaxLength, AddressTranslator).Combine( - addressUnits); + new AddressCombinerNumericJump((int) (count * Percentage / 100.0), MaxLength, AddressTranslator) + .Combine( + addressUnits); } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/AddressHelper.cs b/Modbus.Net/src/Base.Common/AddressHelper.cs index cb8dcf9..ce16ee6 100644 --- a/Modbus.Net/src/Base.Common/AddressHelper.cs +++ b/Modbus.Net/src/Base.Common/AddressHelper.cs @@ -17,7 +17,7 @@ namespace Modbus.Net public static double MapAbstractCoordinateToProtocalCoordinate(double abstractAddress, int startAddress, double byteLength) { - return abstractAddress/byteLength + startAddress; + return abstractAddress / byteLength + startAddress; } /// @@ -30,7 +30,7 @@ namespace Modbus.Net public static double MapProtocalCoordinateToAbstractCoordinate(double protocalAddress, int startAddress, double byteLength) { - return (protocalAddress - startAddress)*byteLength; + return (protocalAddress - startAddress) * byteLength; } /// @@ -43,7 +43,7 @@ namespace Modbus.Net public static double MapProtocalGetCountToAbstractByteCount(double protocalGetCount, double areaLength, double byteLength) { - return protocalGetCount*areaLength + byteLength; + return protocalGetCount * areaLength + byteLength; } /// @@ -55,7 +55,7 @@ namespace Modbus.Net /// public static double GetProtocalCoordinate(int address, int subAddress, double byteLength) { - return address + subAddress*(0.125/byteLength); + return address + subAddress * (0.125 / byteLength); } /// @@ -66,7 +66,7 @@ namespace Modbus.Net /// public static double GetAbstractCoordinate(int address, int subAddress) { - return address + subAddress*0.125; + return address + subAddress * 0.125; } /// @@ -80,7 +80,7 @@ namespace Modbus.Net double byteLength) { return protocalAddress + - BigEndianValueHelper.Instance.ByteLength[nextPositionBetweenType.FullName]/byteLength; + BigEndianValueHelper.Instance.ByteLength[nextPositionBetweenType.FullName] / byteLength; } /// diff --git a/Modbus.Net/src/Base.Common/AddressTranslator.cs b/Modbus.Net/src/Base.Common/AddressTranslator.cs index 39c1c68..98553a3 100644 --- a/Modbus.Net/src/Base.Common/AddressTranslator.cs +++ b/Modbus.Net/src/Base.Common/AddressTranslator.cs @@ -11,14 +11,17 @@ namespace Modbus.Net /// 地址区域的字符串描述 /// public string AreaString { get; set; } + /// /// 地址区域的数字描述 /// public int Area { get; set; } + /// /// 地址 /// public int Address { get; set; } + /// /// 子地址 /// @@ -34,6 +37,7 @@ namespace Modbus.Net /// 地址区域的编码 /// public int Code { get; set; } + /// /// 地址区域的单个地址占用的字节数 /// @@ -79,26 +83,22 @@ namespace Modbus.Net if (split.Length == 2) { if (int.TryParse(split[0], out num1) && int.TryParse(split[1], out num2)) - { return new AddressDef { Area = num1, Address = num2 }; - } } else if (split.Length == 3) { if (int.TryParse(split[0], out num1) && int.TryParse(split[1], out num2) && int.TryParse(split[3], out num3)) - { return new AddressDef { Area = num1, Address = num2, SubAddress = num3 }; - } } throw new FormatException(); } diff --git a/Modbus.Net/src/Base.Common/AsyncHelper.cs b/Modbus.Net/src/Base.Common/AsyncHelper.cs index 842fd28..ea16dce 100644 --- a/Modbus.Net/src/Base.Common/AsyncHelper.cs +++ b/Modbus.Net/src/Base.Common/AsyncHelper.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace Modbus.Net { /// - /// AsyncHelper Class + /// AsyncHelper Class /// public static class AsyncHelper { diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 6f8bf21..3cfabb5 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -28,7 +28,7 @@ namespace Modbus.Net /// /// Id - /// + /// Id } @@ -54,7 +54,7 @@ namespace Modbus.Net /// /// Id - /// + /// Id } @@ -80,7 +80,7 @@ namespace Modbus.Net /// /// Id - /// + /// Id } @@ -125,7 +125,8 @@ namespace Modbus.Net /// /// 设备的Id类型 /// 设备中使用的AddressUnit的Id类型 - public abstract class BaseMachine : IMachineMethodData, IMachineProperty where TKey : IEquatable + public abstract class BaseMachine : IMachineMethodData, IMachineProperty + where TKey : IEquatable where TUnitKey : IEquatable { private readonly int _maxErrorCount = 3; @@ -166,11 +167,6 @@ namespace Modbus.Net private int ErrorCount { get; set; } - /// - /// 是否处于连接状态 - /// - public bool IsConnected => BaseUtility.IsConnected; - /// /// 地址编码器 /// @@ -206,11 +202,6 @@ namespace Modbus.Net /// public IEnumerable> GetAddresses { get; set; } - /// - /// 是否保持连接 - /// - public bool KeepConnect { get; set; } - /// /// 从站号 /// @@ -221,31 +212,6 @@ namespace Modbus.Net /// public byte MasterAddress { get; set; } - /// - /// 设备的连接器 - /// - public IUtilityProperty BaseUtility { get; protected set; } - - /// - /// 设备的Id - /// - public TKey Id { get; set; } - - /// - /// 设备所在工程的名称 - /// - public string ProjectName { get; set; } - - /// - /// 设备的名称 - /// - public string MachineName { get; set; } - - /// - /// 标识设备的连接关键字 - /// - public string ConnectionToken => BaseUtility.ConnectionToken; - /// /// 读取数据 /// @@ -267,9 +233,7 @@ namespace Modbus.Net var ans = new Dictionary(); //检测并连接设备 if (!BaseUtility.IsConnected) - { await BaseUtility.ConnectAsync(); - } //如果无法连接,终止 if (!BaseUtility.IsConnected) return null; //遍历每一个实际向设备获取数据的连续地址 @@ -282,17 +246,17 @@ namespace Modbus.Net AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, communicateAddress.SubAddress), (int) - Math.Ceiling(communicateAddress.GetCount* - BigEndianValueHelper.Instance.ByteLength[ - communicateAddress.DataType.FullName])); + Math.Ceiling(communicateAddress.GetCount * + BigEndianValueHelper.Instance.ByteLength[ + communicateAddress.DataType.FullName])); //如果没有数据,终止 - if (datas == null || (datas.Length != 0 && datas.Length < - (int) - Math.Ceiling(communicateAddress.GetCount* - BigEndianValueHelper.Instance.ByteLength[ - communicateAddress.DataType.FullName]))) + if (datas == null || datas.Length != 0 && datas.Length < + (int) + Math.Ceiling(communicateAddress.GetCount * + BigEndianValueHelper.Instance.ByteLength[ + communicateAddress.DataType.FullName])) return null; @@ -300,13 +264,13 @@ namespace Modbus.Net { //字节坐标的位置 var localPos = AddressHelper.MapProtocalCoordinateToAbstractCoordinate(address.Address, - communicateAddress.Address, - AddressTranslator.GetAreaByteLength(communicateAddress.Area)) + - address.SubAddress*0.125; + communicateAddress.Address, + AddressTranslator.GetAreaByteLength(communicateAddress.Area)) + + address.SubAddress * 0.125; //字节坐标的主地址位置 var localMainPos = (int) localPos; //字节坐标的子地址位置 - var localSubPos = (int) ((localPos - localMainPos)*8); + var localSubPos = (int) ((localPos - localMainPos) * 8); //根据类型选择返回结果的键是通讯标识还是地址 string key; @@ -341,16 +305,12 @@ namespace Modbus.Net //如果没有数据返回空 if (datas.Length == 0) - { ans.Add(key, new ReturnUnit { PlcValue = null, UnitExtend = address.UnitExtend }); - } else - { - //将获取的数据和对应的通讯标识对应 ans.Add(key, new ReturnUnit { @@ -358,17 +318,14 @@ namespace Modbus.Net Convert.ToDouble( ValueHelper.GetInstance(BaseUtility.Endian) .GetValue(datas, ref localMainPos, ref localSubPos, - address.DataType))*address.Zoom, + address.DataType)) * address.Zoom, UnitExtend = address.UnitExtend }); - } } } //如果不保持连接,断开连接 if (!KeepConnect) - { BaseUtility.Disconnect(); - } //返回数据 if (ans.All(p => p.Value.PlcValue == null)) ans = null; ErrorCount = 0; @@ -379,9 +336,7 @@ namespace Modbus.Net Console.WriteLine(ConnectionToken + " " + e.Message); ErrorCount++; if (ErrorCount >= _maxErrorCount) - { Disconnect(); - } return null; } } @@ -409,9 +364,7 @@ namespace Modbus.Net { //检测并连接设备 if (!BaseUtility.IsConnected) - { await BaseUtility.ConnectAsync(); - } //如果设备无法连接,终止 if (!BaseUtility.IsConnected) return false; var addresses = new List>(); @@ -428,8 +381,8 @@ namespace Modbus.Net GetAddresses.SingleOrDefault( p => AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key || - (p.DataType != typeof (bool) && - AddressFormater.FormatAddress(p.Area, p.Address) == value.Key)); + p.DataType != typeof(bool) && + AddressFormater.FormatAddress(p.Area, p.Address) == value.Key); break; } case MachineSetDataType.CommunicationTag: @@ -478,10 +431,11 @@ namespace Modbus.Net var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address); - var datasReturn = await BaseUtility.InvokeUtilityMethod>("GetDatasAsync", - AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0), - (int) - Math.Ceiling(communicateAddress.GetCount* + var datasReturn = + await BaseUtility.InvokeUtilityMethod>("GetDatasAsync", + AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0), + (int) + Math.Ceiling(communicateAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[ communicateAddress.DataType.FullName])); @@ -492,9 +446,9 @@ namespace Modbus.Net //如果没有数据,终止 if (datas == null || datas.Length < (int) - Math.Ceiling(communicateAddress.GetCount* - BigEndianValueHelper.Instance.ByteLength[ - communicateAddress.DataType.FullName])) + Math.Ceiling(communicateAddress.GetCount * + BigEndianValueHelper.Instance.ByteLength[ + communicateAddress.DataType.FullName])) return false; foreach (var addressUnit in communicateAddress.OriginalAddresses) @@ -503,21 +457,21 @@ namespace Modbus.Net var byteCount = AddressHelper.MapProtocalGetCountToAbstractByteCount( addressUnit.Address - communicateAddress.Address + - addressUnit.SubAddress*0.125/ + addressUnit.SubAddress * 0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area), AddressTranslator.GetAreaByteLength(communicateAddress.Area), 0); //字节坐标主地址 var mainByteCount = (int) byteCount; //字节坐标自地址 - var localByteCount = (int) ((byteCount - (int) byteCount)*8); + var localByteCount = (int) ((byteCount - (int) byteCount) * 8); //协议坐标地址 - var localPos = byteCount/AddressTranslator.GetAreaByteLength(communicateAddress.Area); + var localPos = byteCount / AddressTranslator.GetAreaByteLength(communicateAddress.Area); //协议坐标子地址 var subPos = (int) - ((localPos - (int) localPos)/ - (0.125/AddressTranslator.GetAreaByteLength(communicateAddress.Area))); + ((localPos - (int) localPos) / + (0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area))); //协议主地址字符串 var address = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address + (int) localPos, subPos); @@ -536,7 +490,7 @@ namespace Modbus.Net //获取要写入的值 value = values.SingleOrDefault( - p => p.Key == address || (address2 != null && p.Key == address2)); + p => p.Key == address || address2 != null && p.Key == address2); break; } case MachineSetDataType.CommunicationTag: @@ -561,22 +515,20 @@ namespace Modbus.Net } } //将要写入的值加入队列 - var data = Convert.ChangeType(value.Value/addressUnit.Zoom, dataType); + var data = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType); if (!valueHelper.SetValue(datas, mainByteCount, localByteCount, data)) return false; } //写入数据 await - BaseUtility.InvokeUtilityMethod>("SetDatasAsync",addressStart, + BaseUtility.InvokeUtilityMethod>("SetDatasAsync", addressStart, valueHelper.ByteArrayToObjectArray(datas, new KeyValuePair(communicateAddress.DataType, communicateAddress.GetCount))); } //如果不保持连接,断开连接 if (!KeepConnect) - { BaseUtility.Disconnect(); - } } catch (Exception e) { @@ -587,22 +539,39 @@ namespace Modbus.Net } /// - /// 通过Id获取数据字段定义 + /// 是否处于连接状态 /// - /// 数据字段Id - /// 数据字段 - public AddressUnit GetAddressUnitById(TUnitKey addressUnitId) - { - try - { - return GetAddresses.SingleOrDefault(p => p.Id.Equals(addressUnitId)); - } - catch (Exception) - { - Console.WriteLine("Id重复,请检查"); - return null; - } - } + public bool IsConnected => BaseUtility.IsConnected; + + /// + /// 是否保持连接 + /// + public bool KeepConnect { get; set; } + + /// + /// 设备的连接器 + /// + public IUtilityProperty BaseUtility { get; protected set; } + + /// + /// 设备的Id + /// + public TKey Id { get; set; } + + /// + /// 设备所在工程的名称 + /// + public string ProjectName { get; set; } + + /// + /// 设备的名称 + /// + public string MachineName { get; set; } + + /// + /// 标识设备的连接关键字 + /// + public string ConnectionToken => BaseUtility.ConnectionToken; /// /// 调用Machine中的方法 @@ -617,24 +586,14 @@ namespace Modbus.Net { if (this is TMachineMethod) { - Type t = typeof(TMachineMethod); - object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) + var t = typeof(TMachineMethod); + var returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) .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; - } - /// /// 连接设备 /// @@ -670,6 +629,34 @@ namespace Modbus.Net { return Id.ToString(); } + + /// + /// 通过Id获取数据字段定义 + /// + /// 数据字段Id + /// 数据字段 + public AddressUnit GetAddressUnitById(TUnitKey addressUnitId) + { + try + { + return GetAddresses.SingleOrDefault(p => p.Id.Equals(addressUnitId)); + } + catch (Exception) + { + Console.WriteLine("Id重复,请检查"); + return null; + } + } + + /// + /// 获取Utility + /// + /// Utility实现的接口名称 + /// + public TUtilityMethod GetUtility() where TUtilityMethod : class, IUtilityMethod + { + return BaseUtility as TUtilityMethod; + } } internal class BaseMachineEqualityComparer : IEqualityComparer> @@ -832,7 +819,7 @@ namespace Modbus.Net /// 是否一致 public bool Equals(AddressUnit other) { - return (Area.ToUpper() == other.Area.ToUpper() && Address == other.Address) || Id.Equals(other.Id); + return Area.ToUpper() == other.Area.ToUpper() && Address == other.Address || Id.Equals(other.Id); } } @@ -915,6 +902,6 @@ namespace Modbus.Net /// /// Id /// - TKey Id { get; set; } + TKey Id { get; set; } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/BaseMachineExtend.cs b/Modbus.Net/src/Base.Common/BaseMachineExtend.cs index 019bbb2..7fb0b73 100644 --- a/Modbus.Net/src/Base.Common/BaseMachineExtend.cs +++ b/Modbus.Net/src/Base.Common/BaseMachineExtend.cs @@ -20,7 +20,7 @@ namespace Modbus.Net return (from getValue in getValues where getValue.Value.PlcValue != null select new KeyValuePair(getValue.Key, getValue.Value.PlcValue.Value)).ToDictionary( - p => p.Key, p => p.Value); + p => p.Key, p => p.Value); } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 627be11..5b7b5f7 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -13,7 +13,8 @@ namespace Modbus.Net /// /// 构造器 /// - protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) + protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian) + : base(slaveAddress, masterAddress, endian) { } @@ -25,13 +26,9 @@ namespace Modbus.Net public override async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) - { await ConnectAsync(); - } if (ProtocalLinker != null) - { return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(Endian, content)); - } return null; } } @@ -39,7 +36,8 @@ namespace Modbus.Net /// /// 基本协议 /// - public abstract class BaseProtocal : IProtocal where TProtocalUnit : ProtocalUnit + public abstract class BaseProtocal : + IProtocal where TProtocalUnit : ProtocalUnit { /// /// 构造器 @@ -56,11 +54,12 @@ namespace Modbus.Net /// 协议的端格式 /// protected Endian Endian { get; set; } - + /// /// 从站地址 /// public byte SlaveAddress { get; set; } + /// /// 主站地址 /// @@ -82,12 +81,10 @@ namespace Modbus.Net { var protocalName = type.FullName; if (Protocals.ContainsKey(protocalName)) - { return Protocals[protocalName]; - } //自动寻找存在的协议并将其加载 var protocalUnit = - Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; + Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容"); protocalUnit.Endian = Endian; Register(protocalUnit); @@ -100,16 +97,6 @@ namespace Modbus.Net /// protected Dictionary Protocals { get; } - /// - /// 注册一个协议 - /// - /// 需要注册的协议 - protected void Register(TProtocalUnit linkProtocal) - { - if (linkProtocal == null) return; - Protocals.Add(linkProtocal.GetType().FullName, linkProtocal); - } - /// /// 发送协议,通过传入需要使用的协议内容和输入结构 /// @@ -121,18 +108,6 @@ namespace Modbus.Net return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); } - /// - /// 发送协议,通过传入需要使用的协议内容和输入结构 - /// - /// 协议的实例 - /// 输入信息的结构化描述 - /// 输出信息的结构化描述 - /// IOutputStruct的具体类型 - public virtual T SendReceive(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct - { - return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); - } - /// /// 发送协议,通过传入需要使用的协议内容和输入结构 /// @@ -141,40 +116,9 @@ namespace Modbus.Net /// 输出信息的结构化描述 public virtual async Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content) { - return await SendReceiveAsync(unit, content); + return await SendReceiveAsync(unit, content); } - /// - /// 发送协议,通过传入需要使用的协议内容和输入结构 - /// - /// 协议的实例 - /// 输入信息的结构化描述 - /// 输出信息的结构化描述 - /// IOutputStruct的具体类型 - public virtual async Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct - { - var t = 0; - var formatContent = unit.Format(content); - if (formatContent != null) - { - TParamOut receiveContent; - //如果为特别处理协议的话,跳过协议扩展收缩 - if (unit is ISpecialProtocalUnit) - { - receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent); - } - else - { - receiveContent = await ProtocalLinker.SendReceiveAsync(formatContent); - } - if (receiveContent != null) - { - return unit.Unformat(receiveContent, ref t); - } - } - return null; - } - /// /// 发送协议内容并接收,一般方法 /// @@ -195,6 +139,54 @@ namespace Modbus.Net throw new NotImplementedException(); } + /// + /// 注册一个协议 + /// + /// 需要注册的协议 + protected void Register(TProtocalUnit linkProtocal) + { + if (linkProtocal == null) return; + Protocals.Add(linkProtocal.GetType().FullName, linkProtocal); + } + + /// + /// 发送协议,通过传入需要使用的协议内容和输入结构 + /// + /// 协议的实例 + /// 输入信息的结构化描述 + /// 输出信息的结构化描述 + /// IOutputStruct的具体类型 + public virtual T SendReceive(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct + { + return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); + } + + /// + /// 发送协议,通过传入需要使用的协议内容和输入结构 + /// + /// 协议的实例 + /// 输入信息的结构化描述 + /// 输出信息的结构化描述 + /// IOutputStruct的具体类型 + public virtual async Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content) + where T : class, IOutputStruct + { + var t = 0; + var formatContent = unit.Format(content); + if (formatContent != null) + { + TParamOut receiveContent; + //如果为特别处理协议的话,跳过协议扩展收缩 + if (unit is ISpecialProtocalUnit) + receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent); + else + receiveContent = await ProtocalLinker.SendReceiveAsync(formatContent); + if (receiveContent != null) + return unit.Unformat(receiveContent, ref t); + } + return null; + } + /// /// 协议连接开始 /// @@ -214,9 +206,7 @@ namespace Modbus.Net public virtual bool Disconnect() { if (ProtocalLinker != null) - { return ProtocalLinker.Disconnect(); - } return false; } } diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index 86172fb..09a4dde 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Threading.Tasks; /// @@ -13,10 +12,12 @@ public enum Endian /// 小端 /// LittleEndianLsb, + /// /// 大端-小端位 /// BigEndianLsb, + /// /// 大端-大端位 /// @@ -26,7 +27,7 @@ public enum Endian namespace Modbus.Net { /// - /// 基础Api入口 + /// 基础Api入口 /// public abstract class BaseUtility : BaseUtility { @@ -35,14 +36,14 @@ namespace Modbus.Net /// protected BaseUtility(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress) { - } } /// - /// 基础Api入口 + /// 基础Api入口 /// - public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData where TProtocalUnit : ProtocalUnit + public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData + where TProtocalUnit : ProtocalUnit { /// /// 协议收发主体 @@ -68,37 +69,12 @@ namespace Modbus.Net /// 从站号 /// public byte SlaveAddress { get; set; } + /// /// 主站号 /// public byte MasterAddress { get; set; } - /// - /// 协议是否遵循小端格式 - /// - public abstract Endian Endian { get; } - - /// - /// 设备是否已经连接 - /// - public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected; - - /// - /// 标识设备的连接关键字 - /// - public string ConnectionToken => Wrapper?.ProtocalLinker == null ? ConnectionString : Wrapper.ProtocalLinker.ConnectionToken; - - /// - /// 地址翻译器 - /// - public AddressTranslator AddressTranslator { get; set; } - - /// - /// 设置连接类型 - /// - /// 连接类型 - public abstract void SetConnectionType(int connectionType); - /// /// 获取数据 /// @@ -144,17 +120,16 @@ namespace Modbus.Net var typeName = getTypeAndCount.Key.FullName; var bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; var getReturnValue = await GetDatasAsync(startAddress, - (int) Math.Ceiling(bCount*getTypeAndCount.Value)); + (int) Math.Ceiling(bCount * getTypeAndCount.Value)); var getBytes = getReturnValue; return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount); - } catch (Exception) { return null; } } - + /// /// 获取数据 /// @@ -181,7 +156,7 @@ namespace Modbus.Net try { var getBytes = await GetDatasAsync(startAddress, - new KeyValuePair(typeof (T), getByteCount)); + new KeyValuePair(typeof(T), getByteCount)); return ValueHelper.GetInstance(Endian).ObjectArrayToDestinationArray(getBytes); } catch (Exception) @@ -203,7 +178,7 @@ namespace Modbus.Net AsyncHelper.RunSync(() => GetDatasAsync(startAddress, getTypeAndCountList)); } - /// GetEndian + /// /// 获取数据 /// /// 开始地址 @@ -219,7 +194,7 @@ namespace Modbus.Net from getTypeAndCount in translateTypeAndCount let typeName = getTypeAndCount.Key.FullName let bCount = BigEndianValueHelper.Instance.ByteLength[typeName] - select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum(); + select (int) Math.Ceiling(bCount * getTypeAndCount.Value)).Sum(); var getReturnValue = await GetDatasAsync(startAddress, bAllCount); var getBytes = getReturnValue; return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount); @@ -249,6 +224,27 @@ namespace Modbus.Net /// 是否设置成功 public abstract Task SetDatasAsync(string startAddress, object[] setContents); + /// + /// 协议是否遵循小端格式 + /// + public abstract Endian Endian { get; } + + /// + /// 设备是否已经连接 + /// + public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected; + + /// + /// 标识设备的连接关键字 + /// + public string ConnectionToken + => Wrapper?.ProtocalLinker == null ? ConnectionString : Wrapper.ProtocalLinker.ConnectionToken; + + /// + /// 地址翻译器 + /// + public AddressTranslator AddressTranslator { get; set; } + /// /// 连接设备 /// @@ -289,13 +285,19 @@ namespace Modbus.Net { if (this is TUtilityMethod) { - Type t = typeof(TUtilityMethod); - object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray(), false) + var t = typeof(TUtilityMethod); + var returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray(), false) .Invoke(this, parameters); - return (TReturnType)returnValue; + return (TReturnType) returnValue; } throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口"); } + + /// + /// 设置连接类型 + /// + /// 连接类型 + public abstract void SetConnectionType(int connectionType); } /// @@ -312,6 +314,7 @@ namespace Modbus.Net /// 设备是否已经连接 /// bool IsConnected { get; } + /// /// 标识设备的连接关键字 /// diff --git a/Modbus.Net/src/Base.Common/CRC16.cs b/Modbus.Net/src/Base.Common/CRC16.cs index 5303dba..478d6e2 100644 --- a/Modbus.Net/src/Base.Common/CRC16.cs +++ b/Modbus.Net/src/Base.Common/CRC16.cs @@ -14,16 +14,15 @@ namespace Modbus.Net { private static Crc16 _crc16; - private Crc16() - { - - } - /// /// CRC验证表 /// private byte[] crc_table = new byte[512]; + private Crc16() + { + } + /// /// 获取校验工具实例 /// @@ -31,9 +30,7 @@ namespace Modbus.Net public static Crc16 GetInstance() { if (_crc16 == null) - { _crc16 = new Crc16(); - } return _crc16; } @@ -51,7 +48,9 @@ namespace Modbus.Net CRC = 0xFFFF; //set all 1 if (Len <= 0) + { CRC = 0; + } else { Len--; @@ -59,13 +58,10 @@ namespace Modbus.Net { CRC = CRC ^ message[IX]; for (IY = 0; IY <= 7; IY++) - { if ((CRC & 1) != 0) CRC = (CRC >> 1) ^ 0xA001; else CRC = CRC >> 1; - // - } } } Rcvbuf[1] = (byte) ((CRC & 0xff00) >> 8); //高位置 @@ -91,9 +87,7 @@ namespace Modbus.Net Array.Copy(byteframe, 0, byteArr, 0, byteArr.Length); GetCRC(byteArr, ref recvbuff); if (recvbuff[0] == byteframe[byteframe.Length - 2] && recvbuff[1] == byteframe[byteframe.Length - 1]) - { return true; - } return false; } @@ -121,7 +115,7 @@ namespace Modbus.Net for (var t = 0; t <= hexArray.GetUpperBound(0); t++) { - if ((hexArray[t] >= 48) && (hexArray[t] <= 57)) + if (hexArray[t] >= 48 && hexArray[t] <= 57) decNum = hexArray[t] - 48; @@ -130,7 +124,7 @@ namespace Modbus.Net if (msb) { - decNumMSB = decNum*16; + decNumMSB = decNum * 16; msb = false; } else @@ -154,12 +148,11 @@ namespace Modbus.Net for (i = 0; decByteTotal > 0; i++) { //b = Convert.ToInt32(System.Math.Pow(16.0, i)); - var a = decByteTotal%16; + var a = decByteTotal % 16; decByteTotal /= 16; if (a <= 9) hexByte = a.ToString(); else - { switch (a) { case 10: @@ -181,7 +174,6 @@ namespace Modbus.Net hexByte = "F"; break; } - } hexTotal = string.Concat(hexByte, hexTotal); } return hexTotal == checkString; @@ -200,15 +192,12 @@ namespace Modbus.Net { byte sum = 0; foreach (var b in code) - { sum += b; - } - sum = (byte)(~sum + 1); //取反+1 + sum = (byte) (~sum + 1); //取反+1 var lrc = sum.ToString("X2"); return lrc; } #endregion - } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IMachineMethod.cs b/Modbus.Net/src/Base.Common/IMachineMethod.cs index c5fc50b..31f23ab 100644 --- a/Modbus.Net/src/Base.Common/IMachineMethod.cs +++ b/Modbus.Net/src/Base.Common/IMachineMethod.cs @@ -1,7 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Modbus.Net @@ -11,7 +8,6 @@ namespace Modbus.Net /// public interface IMachineMethod { - } /// diff --git a/Modbus.Net/src/Base.Common/IProtocal.cs b/Modbus.Net/src/Base.Common/IProtocal.cs index b2b4fae..2bb48bd 100644 --- a/Modbus.Net/src/Base.Common/IProtocal.cs +++ b/Modbus.Net/src/Base.Common/IProtocal.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Modbus.Net { @@ -12,7 +8,8 @@ namespace Modbus.Net /// 向Connector传入的类型 /// 从Connector返回的类型 /// 协议单元的类型 - public interface IProtocal where TProtocalUnit : IProtocalFormatting + public interface IProtocal + where TProtocalUnit : IProtocalFormatting { /// /// 发送协议内容并接收,一般方法 @@ -44,4 +41,4 @@ namespace Modbus.Net /// 输出信息的结构化描述 Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content); } -} +} \ 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 d494e8c..b9ff233 100644 --- a/Modbus.Net/src/Base.Common/IProtocalFormatting.cs +++ b/Modbus.Net/src/Base.Common/IProtocalFormatting.cs @@ -5,7 +5,6 @@ /// public interface IProtocalFormatting : IProtocalFormatting { - } /// @@ -38,12 +37,12 @@ IOutputStruct Unformat(TParamOut messageBytes, ref int pos); /// - /// 把仪器返回的内容填充到输出结构中 - /// - /// 返回数据的字节流 - /// 转换标记位 - /// IOutputStruct的具体类型 - /// 结构化的输出数据 + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// IOutputStruct的具体类型 + /// 结构化的输出数据 T Unformat(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct; } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IProtocalLinker.cs b/Modbus.Net/src/Base.Common/IProtocalLinker.cs index 94633ad..eb1091a 100644 --- a/Modbus.Net/src/Base.Common/IProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/IProtocalLinker.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Modbus.Net { @@ -62,4 +58,4 @@ namespace Modbus.Net /// 缩减后的协议内容 TParamOut BytesDecact(TParamOut content); } -} +} \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs b/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs index 77f168e..ef2af9d 100644 --- a/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs +++ b/Modbus.Net/src/Base.Common/IProtocalLinkerBytesExtend.cs @@ -5,7 +5,6 @@ /// public interface IProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend { - } /// diff --git a/Modbus.Net/src/Base.Common/IUtilityMethod.cs b/Modbus.Net/src/Base.Common/IUtilityMethod.cs index a6b9deb..ce526ee 100644 --- a/Modbus.Net/src/Base.Common/IUtilityMethod.cs +++ b/Modbus.Net/src/Base.Common/IUtilityMethod.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Modbus.Net @@ -11,7 +9,6 @@ namespace Modbus.Net /// public interface IUtilityMethod { - } /// @@ -19,6 +16,14 @@ namespace Modbus.Net /// public interface IUtilityMethodData : IUtilityMethod { + /// + /// 获取数据 + /// + /// 开始地址 + /// 获取字节数个数 + /// 接收到的byte数据 + byte[] GetDatas(string startAddress, int getByteCount); + /// /// 获取数据 /// @@ -69,7 +74,7 @@ namespace Modbus.Net /// 获取数据的对象数组,请强制转换成相应类型 object[] GetDatas(string startAddress, IEnumerable> getTypeAndCountList); - /// GetEndian + /// /// 获取数据 /// /// 开始地址 @@ -94,11 +99,10 @@ namespace Modbus.Net } /// - /// Utility的时间读写接口 + /// Utility的时间读写接口 /// public interface IUtilityMethodTime : IUtilityMethod { - /// /// 获取PLC时间 /// @@ -111,6 +115,5 @@ namespace Modbus.Net /// 设置PLC时间 /// 设置是否成功 Task SetTimeAsync(DateTime setTime); - } -} +} \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index 3ec9995..bd7accd 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -45,7 +45,8 @@ namespace Modbus.Net { //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。 var bytesExtend = - Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as + Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) + as IProtocalLinkerBytesExtend; return bytesExtend?.BytesExtend(content); } @@ -59,7 +60,8 @@ namespace Modbus.Net { //自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。 var bytesExtend = - Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as + Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) + as IProtocalLinkerBytesExtend; return bytesExtend?.BytesDecact(content); } @@ -85,33 +87,6 @@ namespace Modbus.Net /// 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(); - } - /// /// 发送并接收数据 /// @@ -192,5 +167,32 @@ 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 f10c579..5360a73 100644 --- a/Modbus.Net/src/Base.Common/ProtocalUnit.cs +++ b/Modbus.Net/src/Base.Common/ProtocalUnit.cs @@ -7,7 +7,6 @@ namespace Modbus.Net /// public abstract class ProtocalUnit : ProtocalUnit { - } /// @@ -20,12 +19,12 @@ namespace Modbus.Net /// public Endian Endian { get; set; } = Endian.BigEndianLsb; - /// - /// 从输入结构格式化 - /// s - /// 结构化的输入数据 - /// 格式化后的字节流 - public abstract TParamIn Format(IInputStruct message); + /// + /// 从输入结构格式化 + /// + /// 结构化的输入数据 + /// 格式化后的字节流 + public abstract TParamIn Format(IInputStruct message); /// /// 从对象的参数数组格式化 @@ -37,25 +36,25 @@ namespace Modbus.Net return TranslateContent(Endian, message); } - /// - /// 把仪器返回的内容填充到输出结构中 - /// - /// 返回数据的字节流 - /// 转换标记位 - /// 结构化的输出数据 - public abstract IOutputStruct Unformat(TParamOut messageBytes, ref int pos); + /// + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// 结构化的输出数据 + public abstract IOutputStruct Unformat(TParamOut messageBytes, ref int pos); - /// - /// 把仪器返回的内容填充到输出结构中 - /// - /// 返回数据的字节流 - /// 转换标记位 - /// IOutputStruct的具体类型 - /// 结构化的输出数据 - public T Unformat(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct - { - return Unformat(messageBytes, ref pos) as T; - } + /// + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// IOutputStruct的具体类型 + /// 结构化的输出数据 + public T Unformat(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct + { + return Unformat(messageBytes, ref pos) as T; + } /// /// 转换静态方法,把对象数组转换为字节数组。 @@ -64,8 +63,8 @@ namespace Modbus.Net /// 对象数组 /// 字节数组 public static byte[] TranslateContent(Endian endian, params object[] contents) - { - return ValueHelper.GetInstance(endian).ObjectArrayToByteArray(contents); + { + return ValueHelper.GetInstance(endian).ObjectArrayToByteArray(contents); } } diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index e73aa17..3169381 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -17,7 +17,6 @@ namespace Modbus.Net /// public class DataReturnDef : DataReturnDef { - } /// @@ -29,6 +28,7 @@ namespace Modbus.Net /// 设备的Id /// public TMachineKey MachineId { get; set; } + /// /// 返回的数据值 /// @@ -141,7 +141,7 @@ namespace Modbus.Net TryExecuteTask(item); } } - // We're done processing items on the current thread + // We're done processing items on the current thread finally { _currentThreadIsProcessingItems = false; @@ -176,7 +176,10 @@ namespace Modbus.Net /// protected sealed override bool TryDequeue(Task task) { - lock (_tasks) return _tasks.Remove(task); + lock (_tasks) + { + return _tasks.Remove(task); + } } /// @@ -213,7 +216,7 @@ namespace Modbus.Net private readonly TaskFactory _tasks; /// - /// 构造函数 + /// 构造函数 /// /// 设备 /// 任务工厂 @@ -278,11 +281,9 @@ namespace Modbus.Net /// 是否停止成功 public bool StopAllTimers() { - bool ans = true; + var ans = true; foreach (var task in TasksWithTimer) - { ans = ans && StopTimer(task.Name); - } return ans; } @@ -308,11 +309,9 @@ namespace Modbus.Net /// 是否暂停成功 public bool PauseAllTimers() { - bool ans = true; + var ans = true; foreach (var task in TasksWithTimer) - { ans = ans && PauseTimer(task.Name); - } return ans; } @@ -338,11 +337,9 @@ namespace Modbus.Net /// 是否恢复成功 public bool ContinueAllTimers() { - bool ans = true; + var ans = true; foreach (var task in TasksWithTimer) - { ans = ans && ContinueTimer(task.Name); - } return ans; } @@ -427,7 +424,7 @@ namespace Modbus.Net return new DataReturnDef { MachineId = machine.GetMachineIdString(), - ReturnValues = ans, + ReturnValues = ans }; }; Params = null; @@ -436,7 +433,7 @@ namespace Modbus.Net TimerTime = getCycle; } } - + /// /// 写入数据的预定义任务 /// @@ -461,7 +458,7 @@ namespace Modbus.Net MachineSetDataType.CommunicationTag).WithCancellation(cts.Token)); return ans; }; - Params = new object[]{values}; + Params = new object[] {values}; Return = returnFunc; } } @@ -472,46 +469,51 @@ namespace Modbus.Net /// 任务返回值的类型 public class TaskItem : ITaskItem, IEquatable> { - /// - /// 名称 - /// - public string Name { get; set; } /// /// 定时器 /// private Timer Timer { get; set; } + /// /// 定时器的时间 /// public int TimerTime { get; set; } + /// /// 离线定时器 /// private Timer TimerDisconnected { get; set; } + /// /// 离线定时器的时间 /// public int TimerDisconnectedTime { get; set; } + /// /// 执行的任务 /// public Func> Invoke { get; set; } + /// /// 检测设备的在线状态 /// - internal Func DetectConnected { get; set; } + internal Func DetectConnected { get; set; } + /// /// 任务执行的参数 /// public object[] Params { get; set; } + /// /// 返回值的处理函数 /// public Action Return { get; set; } + /// /// 获取设备 /// internal Func GetMachine { get; set; } + /// /// 获取任务工厂 /// @@ -527,6 +529,11 @@ namespace Modbus.Net return Name == other?.Name; } + /// + /// 名称 + /// + public string Name { get; set; } + /// /// 启动定时器 /// @@ -537,6 +544,17 @@ namespace Modbus.Net return true; } + /// + /// 停止定时器 + /// + /// + public bool StopTimer() + { + DeactivateTimer(); + DeactivateTimerDisconnected(); + return true; + } + /// /// 激活定时器 /// @@ -545,7 +563,7 @@ namespace Modbus.Net Timer = new Timer(async state => { if (!DetectConnected()) TimerChangeToDisconnect(); - var ans = await Invoke(GetMachine(),GetTaskFactory(),Params); + var ans = await Invoke(GetMachine(), GetTaskFactory(), Params); Return?.Invoke(ans); }, null, 0, TimerTime); } @@ -601,17 +619,6 @@ namespace Modbus.Net ActivateTimerDisconnected(); return true; } - - /// - /// 停止定时器 - /// - /// - public bool StopTimer() - { - DeactivateTimer(); - DeactivateTimerDisconnected(); - return true; - } } /// @@ -719,16 +726,6 @@ namespace Modbus.Net _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); } - /// - /// 强制停止所有正在运行的任务 - /// - public void TaskHalt() - { - _cts.Cancel(); - _cts = new CancellationTokenSource(); - _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); - } - /// /// 保持连接 /// @@ -742,9 +739,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { machine.Machine.KeepConnect = _keepConnect; - } } ContinueTimerAll(); } @@ -791,6 +786,7 @@ namespace Modbus.Net /// 设备读数据的关键字 /// public MachineGetDataType GetDataType { get; set; } + /// /// 设备写数据的关键字 /// @@ -810,6 +806,16 @@ namespace Modbus.Net } } + /// + /// 强制停止所有正在运行的任务 + /// + public void TaskHalt() + { + _cts.Cancel(); + _cts = new CancellationTokenSource(); + _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); + } + /// /// 添加一台设备 /// @@ -834,9 +840,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in machines) - { AddMachine(machine); - } } } @@ -922,7 +926,7 @@ namespace Modbus.Net { lock (_machines) { - _machines.RemoveWhere(p=>p.Machine.Equals(machine)); + _machines.RemoveWhere(p => p.Machine.Equals(machine)); } } @@ -938,9 +942,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { ans &= machine.InvokeTimer(item); - } } return ans; } @@ -955,9 +957,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { ans &= machine.StopAllTimers(); - } } return ans; } @@ -973,9 +973,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { ans &= machine.StopTimer(taskItemName); - } } return ans; } @@ -990,9 +988,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { ans &= machine.PauseAllTimers(); - } } return ans; } @@ -1008,9 +1004,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { ans &= machine.PauseTimer(taskItemName); - } } return ans; } @@ -1025,9 +1019,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { ans &= machine.ContinueAllTimers(); - } } return ans; } @@ -1042,9 +1034,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { machine.ContinueTimer(taskItemName); - } } return true; } @@ -1061,12 +1051,10 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - { tasks.Add(machine.InvokeOnce(item)); - } } var ans = await Task.WhenAll(tasks); - return ans.All(p=>p); + return ans.All(p => p); } /// @@ -1080,9 +1068,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - { return await machine.InvokeOnce(item); - } return false; } @@ -1097,9 +1083,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - { return machine.InvokeTimer(item); - } return false; } @@ -1113,9 +1097,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - { return machine.StopTimer(taskItemName); - } return false; } @@ -1129,9 +1111,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - { return machine.PauseTimer(taskItemName); - } return false; } @@ -1145,9 +1125,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - { return machine.ContinueTimer(taskItemName); - } return false; } } diff --git a/Modbus.Net/src/Base.Common/TcpConnector.cs b/Modbus.Net/src/Base.Common/TcpConnector.cs index 2b354e3..8317870 100644 --- a/Modbus.Net/src/Base.Common/TcpConnector.cs +++ b/Modbus.Net/src/Base.Common/TcpConnector.cs @@ -74,9 +74,7 @@ namespace Modbus.Net { _timeoutTime = value; if (_socketClient != null) - { _socketClient.ReceiveTimeout = _timeoutTime; - } } } @@ -144,9 +142,7 @@ namespace Modbus.Net public override async Task ConnectAsync() { if (_socketClient != null) - { Disconnect(); - } try { _socketClient = new TcpClient @@ -187,9 +183,7 @@ namespace Modbus.Net public override bool Disconnect() { if (_socketClient == null) - { return true; - } try { @@ -239,9 +233,7 @@ namespace Modbus.Net try { if (!IsConnected) - { await ConnectAsync(); - } var stream = _socketClient.GetStream(); await stream.WriteAsync(datagram, 0, datagram.Length); @@ -280,9 +272,7 @@ namespace Modbus.Net try { if (!IsConnected) - { await ConnectAsync(); - } var stream = _socketClient.GetStream(); await stream.WriteAsync(datagram, 0, datagram.Length); @@ -313,9 +303,7 @@ namespace Modbus.Net stream.Flush(); // 异步接收回答 if (len > 0) - { return CheckReplyDatagram(len); - } return null; } catch (Exception err) @@ -339,9 +327,7 @@ namespace Modbus.Net RefreshReceiveCount(); if (len <= 0) - { RefreshErrorCount(); - } return replyMessage; } diff --git a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs index b353cd8..6a86707 100644 --- a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs @@ -1,4 +1,5 @@ -#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47 + +#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47 using System.Configuration; #endif diff --git a/Modbus.Net/src/Base.Common/TypeExtensions.cs b/Modbus.Net/src/Base.Common/TypeExtensions.cs index fb8778d..b81436f 100644 --- a/Modbus.Net/src/Base.Common/TypeExtensions.cs +++ b/Modbus.Net/src/Base.Common/TypeExtensions.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace Modbus.Net { @@ -16,21 +13,21 @@ namespace Modbus.Net #region Public Methods /// - /// Looks for the method in the type matching the name and arguments. + /// Looks for the method in the type matching the name and arguments. /// /// /// - /// The name of the method to find. + /// The name of the method to find. /// /// - /// The types of the method's arguments to match. + /// The types of the method's arguments to match. /// /// - /// Is method Generic Method. + /// Is method Generic Method. /// /// /// - /// Thrown if: + /// Thrown if: /// - The name of the method is not specified. /// public static MethodInfo GetRuntimeMethod(this Type type, string methodName, Type[] args, bool isGenericMethod) @@ -42,26 +39,23 @@ namespace Modbus.Net throw new ArgumentNullException("methodName", "The name of the method has not been specified."); - var methods = type.GetRuntimeMethods().Where(methodInfo => string.Equals(methodInfo.Name, methodName, StringComparison.OrdinalIgnoreCase)).ToList(); + var methods = + type.GetRuntimeMethods() + .Where(methodInfo => string.Equals(methodInfo.Name, methodName, StringComparison.OrdinalIgnoreCase)) + .ToList(); if (!methods.Any()) - return null; // No methods have the specified name. + return null; // No methods have the specified name. if (isGenericMethod) - { methods = methods.Where(method => method.IsGenericMethod).ToList(); - } else - { methods = methods.Where(method => !method.IsGenericMethod).ToList(); - } var ans = methods.Where(method => IsSignatureMatch(method, args)); if (ans.Count() <= 1) - { - return ans.Count() == 1 ? ans.Single() : null; - } + return ans.Count() == 1 ? ans.Single() : null; // Oh noes, don't make me go there. throw new NotImplementedException("Resolving overloaded methods is not implemented as of now."); @@ -72,7 +66,7 @@ namespace Modbus.Net #region Private Methods /// - /// Finds out if the provided arguments matches the specified method's signature. + /// Finds out if the provided arguments matches the specified method's signature. /// /// /// @@ -83,11 +77,11 @@ namespace Modbus.Net // Gets the parameters of the method to analyze. - ParameterInfo[] parameters = methodInfo.GetParameters(); + var parameters = methodInfo.GetParameters(); - int currentArgId = 0; + var currentArgId = 0; - foreach (ParameterInfo parameterInfo in parameters) + foreach (var parameterInfo in parameters) { if (!ReferenceEquals(args, null) && currentArgId < args.Length) { @@ -102,7 +96,7 @@ namespace Modbus.Net if (parameterInfo.ParameterType.IsGenericParameter) { // Gets the base type of the generic parameter. - Type baseType = parameterInfo.ParameterType.GetTypeInfo().BaseType; + var baseType = parameterInfo.ParameterType.GetTypeInfo().BaseType; // TODO: This is not good v and works with the most simple situation. @@ -129,4 +123,4 @@ namespace Modbus.Net #endregion } -} +} \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/ValueHelper.cs b/Modbus.Net/src/Base.Common/ValueHelper.cs index 01b34b3..01a2897 100644 --- a/Modbus.Net/src/Base.Common/ValueHelper.cs +++ b/Modbus.Net/src/Base.Common/ValueHelper.cs @@ -410,7 +410,7 @@ namespace Modbus.Net var temp = data[pos]; for (var i = 0; i < 8; i++) { - t[i] = temp%2 > 0; + t[i] = temp % 2 > 0; temp /= 2; } pos += 1; @@ -427,11 +427,11 @@ namespace Modbus.Net public bool GetBit(byte number, ref int pos, ref int subPos) { if (subPos < 0 && subPos >= 8) throw new IndexOutOfRangeException(); - var ans = number%2; + var ans = number % 2; var i = 0; while (i <= subPos) { - ans = number%2; + ans = number % 2; number /= 2; i++; } @@ -491,7 +491,7 @@ namespace Modbus.Net b = true; //自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组 var contentArray = - ArrayList.Adapter((Array) content).ToArray(typeof (object)).OfType(); + ArrayList.Adapter((Array) content).ToArray(typeof(object)).OfType(); newContentsList.AddRange(contentArray); } else @@ -520,13 +520,9 @@ namespace Modbus.Net } lastIsBool = true; if (!LittleEndianBit) - { - boolToByteTemp = (byte) (boolToByteTemp*2 + ((bool) content ? 1 : 0)); - } + boolToByteTemp = (byte) (boolToByteTemp * 2 + ((bool) content ? 1 : 0)); else - { boolToByteTemp += (byte) ((bool) content ? Math.Pow(2, boolToByteCount) : 0); - } boolToByteCount++; } else @@ -594,9 +590,7 @@ namespace Modbus.Net } //最后是bool拼装时,表示数字还没有添加,把数字添加进返回数组中。 if (lastIsBool) - { translateTarget.Add(boolToByteTemp); - } //最后把队列转换为数组 return translateTarget.ToArray(); } @@ -622,7 +616,7 @@ namespace Modbus.Net public virtual T[] ByteArrayToDestinationArray(byte[] contents, int getCount) { var objectArray = _Instance.ByteArrayToObjectArray(contents, - new KeyValuePair(typeof (T), getCount)); + new KeyValuePair(typeof(T), getCount)); return _Instance.ObjectArrayToDestinationArray(objectArray); } @@ -641,7 +635,6 @@ namespace Modbus.Net var translation = new List(); var count = 0; foreach (var translateUnit in translateTypeAndCount) - { for (var i = 0; i < translateUnit.Value; i++) { if (count >= contents.Length) break; @@ -708,9 +701,7 @@ namespace Modbus.Net var value = _Instance.GetBits(contents, ref count); var k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8; for (var j = 0; j < k; j++) - { translation.Add(value[j]); - } i += 7; break; } @@ -725,7 +716,6 @@ namespace Modbus.Net count = contents.Length; } } - } return translation.ToArray(); } @@ -906,21 +896,21 @@ namespace Modbus.Net switch (endian) { case Endian.LittleEndianLsb: - { - return ValueHelper.Instance; - } + { + return Instance; + } case Endian.BigEndianLsb: - { - return BigEndianValueHelper.Instance; - } + { + return BigEndianValueHelper.Instance; + } case Endian.BigEndianMsb: - { - return BigEndianMsbValueHelper.Instance; - } + { + return BigEndianMsbValueHelper.Instance; + } default: - { - return ValueHelper.Instance; - } + { + return Instance; + } } } diff --git a/Samples/AnyType/AnyType.csproj b/Samples/AnyType/AnyType.csproj index bdb405f..333f7e2 100644 --- a/Samples/AnyType/AnyType.csproj +++ b/Samples/AnyType/AnyType.csproj @@ -25,6 +25,7 @@ + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib true @@ -44,11 +45,19 @@ 4 + + ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll + ..\..\Modbus.Net\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True + + ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + @@ -58,6 +67,27 @@ + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + @@ -67,54 +97,13 @@ - - True - ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - True + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib\WebGrease.dll - - True - ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll - - - - - ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll - @@ -128,6 +117,8 @@ + + @@ -136,6 +127,10 @@ + + + + @@ -161,17 +156,11 @@ + - - - - - - - {fdca72ba-6d06-4de0-b873-c11c4ac853ad} @@ -212,7 +201,7 @@ - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + 此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 diff --git a/Samples/AnyType/Content/bootstrap-theme.css b/Samples/AnyType/Content/bootstrap-theme.css new file mode 100644 index 0000000..ad11735 --- /dev/null +++ b/Samples/AnyType/Content/bootstrap-theme.css @@ -0,0 +1,384 @@ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn:active, +.btn.active { + background-image: none; +} + +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); + background-repeat: repeat-x; + border-color: #e0e0e0; + border-color: #ccc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); +} + +.btn-default:active, +.btn-default.active { + background-color: #e6e6e6; + border-color: #e0e0e0; +} + +.btn-primary { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + border-color: #2d6ca2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.btn-primary:active, +.btn-primary.active { + background-color: #3071a9; + border-color: #2d6ca2; +} + +.btn-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + border-color: #419641; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.btn-success:active, +.btn-success.active { + background-color: #449d44; + border-color: #419641; +} + +.btn-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + border-color: #eb9316; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.btn-warning:active, +.btn-warning.active { + background-color: #ec971f; + border-color: #eb9316; +} + +.btn-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + border-color: #c12e2a; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.btn-danger:active, +.btn-danger.active { + background-color: #c9302c; + border-color: #c12e2a; +} + +.btn-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + border-color: #2aabd2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.btn-info:active, +.btn-info.active { + background-color: #31b0d5; + border-color: #2aabd2; +} + +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #357ebd; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.navbar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); + background-repeat: repeat-x; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); +} + +.navbar .navbar-nav > .active > a { + background-color: #f8f8f8; +} + +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} + +.navbar-inverse { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); + background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); + background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); +} + +.navbar-inverse .navbar-nav > .active > a { + background-color: #222222; +} + +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} + +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.alert-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + background-repeat: repeat-x; + border-color: #b2dba1; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); +} + +.alert-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + background-repeat: repeat-x; + border-color: #9acfea; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); +} + +.alert-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + background-repeat: repeat-x; + border-color: #f5e79e; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); +} + +.alert-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + background-repeat: repeat-x; + border-color: #dca7a7; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); +} + +.progress { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); +} + +.progress-bar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.progress-bar-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.progress-bar-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.progress-bar-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.progress-bar-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #3071a9; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); + background-repeat: repeat-x; + border-color: #3278b3; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); +} + +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.panel-default > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); + background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); + background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); +} + +.panel-primary > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.panel-success > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); +} + +.panel-info > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); +} + +.panel-warning > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); +} + +.panel-danger > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); +} + +.well { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + background-repeat: repeat-x; + border-color: #dcdcdc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/Samples/AnyType/Content/bootstrap-theme.min.css b/Samples/AnyType/Content/bootstrap-theme.min.css new file mode 100644 index 0000000..cad36b4 --- /dev/null +++ b/Samples/AnyType/Content/bootstrap-theme.min.css @@ -0,0 +1 @@ +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file diff --git a/Samples/AnyType/Content/bootstrap.css b/Samples/AnyType/Content/bootstrap.css index 6d6e682..bbda4ee 100644 --- a/Samples/AnyType/Content/bootstrap.css +++ b/Samples/AnyType/Content/bootstrap.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/AnyType/Content/bootstrap.min.css b/Samples/AnyType/Content/bootstrap.min.css index df89a50..a553c4f 100644 --- a/Samples/AnyType/Content/bootstrap.min.css +++ b/Samples/AnyType/Content/bootstrap.min.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/AnyType/Scripts/_references.js b/Samples/AnyType/Scripts/_references.js index 56fa13a1eeb46f53498c56c8a34f0efd01cf0dbd..eba5c8d504a5c3227262933a66d65b508a357aef 100644 GIT binary patch literal 339 zcmb8rF%H5o3)$T3{GYRuj=W=LAu<972A50{L*RJEyh?-a67T4JX#f*aAdS~%lM nmm`uS4AU$#R2k@m_o zYEUbyyBeLiGuTYIYIcPVTH)`BGVCI=eOqgA?jEj@Y@P1LDXqSMtgevq;VuBa?f)}y!7 b0~>qdZZ").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+"")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery); \ No newline at end of file diff --git a/Samples/AnyType/Scripts/respond.js b/Samples/AnyType/Scripts/respond.js index 378d773..6690827 100644 --- a/Samples/AnyType/Scripts/respond.js +++ b/Samples/AnyType/Scripts/respond.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia = window.matchMedia || (function(doc, undefined){ diff --git a/Samples/AnyType/Scripts/respond.min.js b/Samples/AnyType/Scripts/respond.min.js index a848137..94e308e 100644 --- a/Samples/AnyType/Scripts/respond.min.js +++ b/Samples/AnyType/Scripts/respond.min.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); diff --git a/Samples/CrossLamp/Content/bootstrap-theme.css b/Samples/CrossLamp/Content/bootstrap-theme.css new file mode 100644 index 0000000..ad11735 --- /dev/null +++ b/Samples/CrossLamp/Content/bootstrap-theme.css @@ -0,0 +1,384 @@ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn:active, +.btn.active { + background-image: none; +} + +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); + background-repeat: repeat-x; + border-color: #e0e0e0; + border-color: #ccc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); +} + +.btn-default:active, +.btn-default.active { + background-color: #e6e6e6; + border-color: #e0e0e0; +} + +.btn-primary { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + border-color: #2d6ca2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.btn-primary:active, +.btn-primary.active { + background-color: #3071a9; + border-color: #2d6ca2; +} + +.btn-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + border-color: #419641; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.btn-success:active, +.btn-success.active { + background-color: #449d44; + border-color: #419641; +} + +.btn-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + border-color: #eb9316; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.btn-warning:active, +.btn-warning.active { + background-color: #ec971f; + border-color: #eb9316; +} + +.btn-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + border-color: #c12e2a; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.btn-danger:active, +.btn-danger.active { + background-color: #c9302c; + border-color: #c12e2a; +} + +.btn-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + border-color: #2aabd2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.btn-info:active, +.btn-info.active { + background-color: #31b0d5; + border-color: #2aabd2; +} + +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #357ebd; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.navbar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); + background-repeat: repeat-x; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); +} + +.navbar .navbar-nav > .active > a { + background-color: #f8f8f8; +} + +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} + +.navbar-inverse { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); + background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); + background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); +} + +.navbar-inverse .navbar-nav > .active > a { + background-color: #222222; +} + +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} + +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.alert-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + background-repeat: repeat-x; + border-color: #b2dba1; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); +} + +.alert-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + background-repeat: repeat-x; + border-color: #9acfea; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); +} + +.alert-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + background-repeat: repeat-x; + border-color: #f5e79e; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); +} + +.alert-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + background-repeat: repeat-x; + border-color: #dca7a7; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); +} + +.progress { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); +} + +.progress-bar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.progress-bar-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.progress-bar-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.progress-bar-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.progress-bar-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #3071a9; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); + background-repeat: repeat-x; + border-color: #3278b3; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); +} + +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.panel-default > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); + background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); + background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); +} + +.panel-primary > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.panel-success > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); +} + +.panel-info > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); +} + +.panel-warning > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); +} + +.panel-danger > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); +} + +.well { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + background-repeat: repeat-x; + border-color: #dcdcdc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/Samples/CrossLamp/Content/bootstrap-theme.min.css b/Samples/CrossLamp/Content/bootstrap-theme.min.css new file mode 100644 index 0000000..cad36b4 --- /dev/null +++ b/Samples/CrossLamp/Content/bootstrap-theme.min.css @@ -0,0 +1 @@ +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file diff --git a/Samples/CrossLamp/Content/bootstrap.css b/Samples/CrossLamp/Content/bootstrap.css index 6d6e682..bbda4ee 100644 --- a/Samples/CrossLamp/Content/bootstrap.css +++ b/Samples/CrossLamp/Content/bootstrap.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/CrossLamp/Content/bootstrap.min.css b/Samples/CrossLamp/Content/bootstrap.min.css index df89a50..a553c4f 100644 --- a/Samples/CrossLamp/Content/bootstrap.min.css +++ b/Samples/CrossLamp/Content/bootstrap.min.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/CrossLamp/CrossLamp.csproj b/Samples/CrossLamp/CrossLamp.csproj index 4be62a2..9036593 100644 --- a/Samples/CrossLamp/CrossLamp.csproj +++ b/Samples/CrossLamp/CrossLamp.csproj @@ -25,6 +25,7 @@ + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib true @@ -44,11 +45,19 @@ 4 + + ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll + ..\..\Modbus.Net\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True + + ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + @@ -58,6 +67,27 @@ + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + @@ -67,54 +97,13 @@ - - True - ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - True + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib\WebGrease.dll - - True - ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll - - - - - ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll - @@ -128,6 +117,8 @@ + + @@ -136,6 +127,10 @@ + + + + @@ -161,17 +156,11 @@ + - - - - - - - {fdca72ba-6d06-4de0-b873-c11c4ac853ad} @@ -212,7 +201,7 @@ - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + 此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 diff --git a/Samples/CrossLamp/Scripts/_references.js b/Samples/CrossLamp/Scripts/_references.js index f4627c7b45bda8bb38d971b6d63064f50a21cc28..c9fc5ae236eee691cf0bb5ffc483cb0b9e5acda0 100644 GIT binary patch literal 340 zcmb8pI}XAy3z0;i@bEV8-yZMO6b3tC}R=3SNg(8%fI4F!@1G>HvF1XTV mi6jd{`ejnj5WEAy|8R+9pEt6fzXStJi4oj-J!4K3U+4k6$86aE literal 676 zcmcJMK@Ng25Jmsm#5)l8sJL*Y-la&55D;yFL=UgNmaQw%5SW(fy!rF{dae|nL^~Pv z>eR~Xu8WTRvqYm@HLF5`glug9 diff --git a/Samples/CrossLamp/Scripts/jquery-1.10.2.js b/Samples/CrossLamp/Scripts/jquery-1.10.2.js index d3e121b..c5c6482 100644 --- a/Samples/CrossLamp/Scripts/jquery-1.10.2.js +++ b/Samples/CrossLamp/Scripts/jquery-1.10.2.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * jQuery JavaScript Library v1.10.2 * http://jquery.com/ diff --git a/Samples/CrossLamp/Scripts/jquery-1.10.2.min.js b/Samples/CrossLamp/Scripts/jquery-1.10.2.min.js index 51aa758..da41706 100644 --- a/Samples/CrossLamp/Scripts/jquery-1.10.2.min.js +++ b/Samples/CrossLamp/Scripts/jquery-1.10.2.min.js @@ -1,20 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * JQUERY CORE 1.10.2; Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; http://jquery.org/license - * Includes Sizzle.js; Copyright 2013 jQuery Foundation, Inc. and other contributors; http://opensource.org/licenses/MIT - * - * NUGET: END LICENSE TEXT */ /*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license //@ sourceMappingURL=jquery-1.10.2.min.map */ diff --git a/Samples/CrossLamp/Scripts/jquery.validate-vsdoc.js b/Samples/CrossLamp/Scripts/jquery.validate-vsdoc.js index fd91257..b1e53c0 100644 --- a/Samples/CrossLamp/Scripts/jquery.validate-vsdoc.js +++ b/Samples/CrossLamp/Scripts/jquery.validate-vsdoc.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /* * This file has been commented to support Visual Studio Intellisense. * You should not use this file at runtime inside the browser--it is only diff --git a/Samples/CrossLamp/Scripts/jquery.validate.js b/Samples/CrossLamp/Scripts/jquery.validate.js index d0a9bc9..88ba300 100644 --- a/Samples/CrossLamp/Scripts/jquery.validate.js +++ b/Samples/CrossLamp/Scripts/jquery.validate.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * jQuery Validation Plugin 1.11.1 * diff --git a/Samples/CrossLamp/Scripts/jquery.validate.min.js b/Samples/CrossLamp/Scripts/jquery.validate.min.js index 3efb648..cbaf510 100644 --- a/Samples/CrossLamp/Scripts/jquery.validate.min.js +++ b/Samples/CrossLamp/Scripts/jquery.validate.min.js @@ -1,16 +1,2 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation * Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(t){t.extend(t.fn,{validate:function(e){if(!this.length)return e&&e.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."),void 0;var i=t.data(this[0],"validator");return i?i:(this.attr("novalidate","novalidate"),i=new t.validator(e,this[0]),t.data(this[0],"validator",i),i.settings.onsubmit&&(this.validateDelegate(":submit","click",function(e){i.settings.submitHandler&&(i.submitButton=e.target),t(e.target).hasClass("cancel")&&(i.cancelSubmit=!0),void 0!==t(e.target).attr("formnovalidate")&&(i.cancelSubmit=!0)}),this.submit(function(e){function s(){var s;return i.settings.submitHandler?(i.submitButton&&(s=t("").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+"")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery); \ No newline at end of file diff --git a/Samples/CrossLamp/Scripts/respond.js b/Samples/CrossLamp/Scripts/respond.js index 378d773..6690827 100644 --- a/Samples/CrossLamp/Scripts/respond.js +++ b/Samples/CrossLamp/Scripts/respond.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia = window.matchMedia || (function(doc, undefined){ diff --git a/Samples/CrossLamp/Scripts/respond.min.js b/Samples/CrossLamp/Scripts/respond.min.js index a848137..94e308e 100644 --- a/Samples/CrossLamp/Scripts/respond.min.js +++ b/Samples/CrossLamp/Scripts/respond.min.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); diff --git a/Samples/TaskManager/Content/bootstrap-theme.css b/Samples/TaskManager/Content/bootstrap-theme.css new file mode 100644 index 0000000..ad11735 --- /dev/null +++ b/Samples/TaskManager/Content/bootstrap-theme.css @@ -0,0 +1,384 @@ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn:active, +.btn.active { + background-image: none; +} + +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); + background-repeat: repeat-x; + border-color: #e0e0e0; + border-color: #ccc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); +} + +.btn-default:active, +.btn-default.active { + background-color: #e6e6e6; + border-color: #e0e0e0; +} + +.btn-primary { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + border-color: #2d6ca2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.btn-primary:active, +.btn-primary.active { + background-color: #3071a9; + border-color: #2d6ca2; +} + +.btn-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + border-color: #419641; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.btn-success:active, +.btn-success.active { + background-color: #449d44; + border-color: #419641; +} + +.btn-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + border-color: #eb9316; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.btn-warning:active, +.btn-warning.active { + background-color: #ec971f; + border-color: #eb9316; +} + +.btn-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + border-color: #c12e2a; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.btn-danger:active, +.btn-danger.active { + background-color: #c9302c; + border-color: #c12e2a; +} + +.btn-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + border-color: #2aabd2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.btn-info:active, +.btn-info.active { + background-color: #31b0d5; + border-color: #2aabd2; +} + +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #357ebd; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.navbar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); + background-repeat: repeat-x; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); +} + +.navbar .navbar-nav > .active > a { + background-color: #f8f8f8; +} + +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} + +.navbar-inverse { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); + background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); + background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); +} + +.navbar-inverse .navbar-nav > .active > a { + background-color: #222222; +} + +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} + +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.alert-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + background-repeat: repeat-x; + border-color: #b2dba1; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); +} + +.alert-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + background-repeat: repeat-x; + border-color: #9acfea; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); +} + +.alert-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + background-repeat: repeat-x; + border-color: #f5e79e; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); +} + +.alert-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + background-repeat: repeat-x; + border-color: #dca7a7; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); +} + +.progress { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); +} + +.progress-bar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.progress-bar-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.progress-bar-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.progress-bar-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.progress-bar-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #3071a9; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); + background-repeat: repeat-x; + border-color: #3278b3; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); +} + +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.panel-default > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); + background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); + background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); +} + +.panel-primary > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.panel-success > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); +} + +.panel-info > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); +} + +.panel-warning > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); +} + +.panel-danger > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); +} + +.well { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + background-repeat: repeat-x; + border-color: #dcdcdc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/Samples/TaskManager/Content/bootstrap-theme.min.css b/Samples/TaskManager/Content/bootstrap-theme.min.css new file mode 100644 index 0000000..cad36b4 --- /dev/null +++ b/Samples/TaskManager/Content/bootstrap-theme.min.css @@ -0,0 +1 @@ +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file diff --git a/Samples/TaskManager/Content/bootstrap.css b/Samples/TaskManager/Content/bootstrap.css index 6d6e682..bbda4ee 100644 --- a/Samples/TaskManager/Content/bootstrap.css +++ b/Samples/TaskManager/Content/bootstrap.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/TaskManager/Content/bootstrap.min.css b/Samples/TaskManager/Content/bootstrap.min.css index df89a50..a553c4f 100644 --- a/Samples/TaskManager/Content/bootstrap.min.css +++ b/Samples/TaskManager/Content/bootstrap.min.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/TaskManager/Scripts/_references.js b/Samples/TaskManager/Scripts/_references.js index 56fa13a1eeb46f53498c56c8a34f0efd01cf0dbd..eba5c8d504a5c3227262933a66d65b508a357aef 100644 GIT binary patch literal 339 zcmb8rF%H5o3)$T3{GYRuj=W=LAu<972A50{L*RJEyh?-a67T4JX#f*aAdS~%lM nmm`uS4AU$#R2k@m_o zYEUbyyBeLiGuTYIYIcPVTH)`BGVCI=eOqgA?jEj@Y@P1LDXqSMtgevq;VuBa?f)}y!7 b0~>qdZZ").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+"")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery); \ No newline at end of file diff --git a/Samples/TaskManager/Scripts/respond.js b/Samples/TaskManager/Scripts/respond.js index 378d773..6690827 100644 --- a/Samples/TaskManager/Scripts/respond.js +++ b/Samples/TaskManager/Scripts/respond.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia = window.matchMedia || (function(doc, undefined){ diff --git a/Samples/TaskManager/Scripts/respond.min.js b/Samples/TaskManager/Scripts/respond.min.js index a848137..94e308e 100644 --- a/Samples/TaskManager/Scripts/respond.min.js +++ b/Samples/TaskManager/Scripts/respond.min.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); diff --git a/Samples/TaskManager/TaskManager.csproj b/Samples/TaskManager/TaskManager.csproj index 1e78793..1754ba8 100644 --- a/Samples/TaskManager/TaskManager.csproj +++ b/Samples/TaskManager/TaskManager.csproj @@ -25,6 +25,7 @@ + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib true @@ -44,11 +45,19 @@ 4 + + ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll + ..\..\Modbus.Net\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True + + ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + @@ -58,6 +67,27 @@ + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + @@ -67,54 +97,13 @@ - - True - ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - True + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib\WebGrease.dll - - True - ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll - - - - - ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll - @@ -128,6 +117,8 @@ + + @@ -136,6 +127,10 @@ + + + + @@ -161,17 +156,11 @@ + - - - - - - - {fdca72ba-6d06-4de0-b873-c11c4ac853ad} @@ -212,7 +201,7 @@ - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + 此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 diff --git a/Samples/TripleAdd/Content/bootstrap-theme.css b/Samples/TripleAdd/Content/bootstrap-theme.css new file mode 100644 index 0000000..ad11735 --- /dev/null +++ b/Samples/TripleAdd/Content/bootstrap-theme.css @@ -0,0 +1,384 @@ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn:active, +.btn.active { + background-image: none; +} + +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); + background-repeat: repeat-x; + border-color: #e0e0e0; + border-color: #ccc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); +} + +.btn-default:active, +.btn-default.active { + background-color: #e6e6e6; + border-color: #e0e0e0; +} + +.btn-primary { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + border-color: #2d6ca2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.btn-primary:active, +.btn-primary.active { + background-color: #3071a9; + border-color: #2d6ca2; +} + +.btn-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + border-color: #419641; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.btn-success:active, +.btn-success.active { + background-color: #449d44; + border-color: #419641; +} + +.btn-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + border-color: #eb9316; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.btn-warning:active, +.btn-warning.active { + background-color: #ec971f; + border-color: #eb9316; +} + +.btn-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + border-color: #c12e2a; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.btn-danger:active, +.btn-danger.active { + background-color: #c9302c; + border-color: #c12e2a; +} + +.btn-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + border-color: #2aabd2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.btn-info:active, +.btn-info.active { + background-color: #31b0d5; + border-color: #2aabd2; +} + +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #357ebd; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.navbar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); + background-repeat: repeat-x; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); +} + +.navbar .navbar-nav > .active > a { + background-color: #f8f8f8; +} + +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} + +.navbar-inverse { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); + background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); + background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); +} + +.navbar-inverse .navbar-nav > .active > a { + background-color: #222222; +} + +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} + +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.alert-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + background-repeat: repeat-x; + border-color: #b2dba1; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); +} + +.alert-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + background-repeat: repeat-x; + border-color: #9acfea; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); +} + +.alert-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + background-repeat: repeat-x; + border-color: #f5e79e; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); +} + +.alert-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + background-repeat: repeat-x; + border-color: #dca7a7; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); +} + +.progress { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); +} + +.progress-bar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.progress-bar-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.progress-bar-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.progress-bar-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.progress-bar-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #3071a9; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); + background-repeat: repeat-x; + border-color: #3278b3; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); +} + +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.panel-default > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); + background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); + background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); +} + +.panel-primary > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.panel-success > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); +} + +.panel-info > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); +} + +.panel-warning > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); +} + +.panel-danger > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); +} + +.well { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + background-repeat: repeat-x; + border-color: #dcdcdc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/Samples/TripleAdd/Content/bootstrap-theme.min.css b/Samples/TripleAdd/Content/bootstrap-theme.min.css new file mode 100644 index 0000000..cad36b4 --- /dev/null +++ b/Samples/TripleAdd/Content/bootstrap-theme.min.css @@ -0,0 +1 @@ +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file diff --git a/Samples/TripleAdd/Content/bootstrap.css b/Samples/TripleAdd/Content/bootstrap.css index 6d6e682..bbda4ee 100644 --- a/Samples/TripleAdd/Content/bootstrap.css +++ b/Samples/TripleAdd/Content/bootstrap.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/TripleAdd/Content/bootstrap.min.css b/Samples/TripleAdd/Content/bootstrap.min.css index df89a50..a553c4f 100644 --- a/Samples/TripleAdd/Content/bootstrap.min.css +++ b/Samples/TripleAdd/Content/bootstrap.min.css @@ -1,14 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. The notices and licenses below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * Bootstrap v3.0.0 * diff --git a/Samples/TripleAdd/Scripts/_references.js b/Samples/TripleAdd/Scripts/_references.js index 9667aef2b2d93ab5705610f425a4e1d86d90f5bc..8c44c9b15feeb492636824ca5b66b05742de97e3 100644 GIT binary patch literal 396 zcmb8rK@Ng25Czb^iFat&w-pwy#Jf!C7)oGTr!5h$=E5U+1z8zm4C4O%|C9f?-L=-@ zz<5GNYET47ZCwoBB9ptatkhmrs*8ot$L;1T?#>x`lBFtlpA>TPaiT^bf$7oKMdFML xUB>$q6GK=tsWN#p7e+UtgbprhaI`8oLhmdj{13m)EeGd28Dskk#o)=l&=XCxf9?PP literal 788 zcmcJNK@Ng25Jmsm#5)l8sJL*Y-UXya2^0h*>fzPb;!anBA#JCfnb$vMo{xpx7ignc z7qu$Y=q9T@XNEOaq8uyLRx|uHQ3fj@Yp1CuKEEf_cn%D=I)Wjpg3#*dvlHkgyT)^3 zd~;>&exqeNdo4A3=U5hY@>baBq>lSTZqFE3A_~szh&Og{bC{{G(EOGBy}GepFI0s3 qNK59`pgIcvLFzle@-lZiA@s!cU~=DEZf@wNA(i)x3Z)jUpQIO#(0_se diff --git a/Samples/TripleAdd/Scripts/jquery-1.10.2.js b/Samples/TripleAdd/Scripts/jquery-1.10.2.js index d3e121b..c5c6482 100644 --- a/Samples/TripleAdd/Scripts/jquery-1.10.2.js +++ b/Samples/TripleAdd/Scripts/jquery-1.10.2.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * jQuery JavaScript Library v1.10.2 * http://jquery.com/ diff --git a/Samples/TripleAdd/Scripts/jquery-1.10.2.min.js b/Samples/TripleAdd/Scripts/jquery-1.10.2.min.js index 51aa758..da41706 100644 --- a/Samples/TripleAdd/Scripts/jquery-1.10.2.min.js +++ b/Samples/TripleAdd/Scripts/jquery-1.10.2.min.js @@ -1,20 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * JQUERY CORE 1.10.2; Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; http://jquery.org/license - * Includes Sizzle.js; Copyright 2013 jQuery Foundation, Inc. and other contributors; http://opensource.org/licenses/MIT - * - * NUGET: END LICENSE TEXT */ /*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license //@ sourceMappingURL=jquery-1.10.2.min.map */ diff --git a/Samples/TripleAdd/Scripts/jquery.validate-vsdoc.js b/Samples/TripleAdd/Scripts/jquery.validate-vsdoc.js index fd91257..b1e53c0 100644 --- a/Samples/TripleAdd/Scripts/jquery.validate-vsdoc.js +++ b/Samples/TripleAdd/Scripts/jquery.validate-vsdoc.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /* * This file has been commented to support Visual Studio Intellisense. * You should not use this file at runtime inside the browser--it is only diff --git a/Samples/TripleAdd/Scripts/jquery.validate.js b/Samples/TripleAdd/Scripts/jquery.validate.js index d0a9bc9..88ba300 100644 --- a/Samples/TripleAdd/Scripts/jquery.validate.js +++ b/Samples/TripleAdd/Scripts/jquery.validate.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! * jQuery Validation Plugin 1.11.1 * diff --git a/Samples/TripleAdd/Scripts/jquery.validate.min.js b/Samples/TripleAdd/Scripts/jquery.validate.min.js index 3efb648..cbaf510 100644 --- a/Samples/TripleAdd/Scripts/jquery.validate.min.js +++ b/Samples/TripleAdd/Scripts/jquery.validate.min.js @@ -1,16 +1,2 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation * Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(t){t.extend(t.fn,{validate:function(e){if(!this.length)return e&&e.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."),void 0;var i=t.data(this[0],"validator");return i?i:(this.attr("novalidate","novalidate"),i=new t.validator(e,this[0]),t.data(this[0],"validator",i),i.settings.onsubmit&&(this.validateDelegate(":submit","click",function(e){i.settings.submitHandler&&(i.submitButton=e.target),t(e.target).hasClass("cancel")&&(i.cancelSubmit=!0),void 0!==t(e.target).attr("formnovalidate")&&(i.cancelSubmit=!0)}),this.submit(function(e){function s(){var s;return i.settings.submitHandler?(i.submitButton&&(s=t("").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+"")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery); \ No newline at end of file diff --git a/Samples/TripleAdd/Scripts/respond.js b/Samples/TripleAdd/Scripts/respond.js index 378d773..6690827 100644 --- a/Samples/TripleAdd/Scripts/respond.js +++ b/Samples/TripleAdd/Scripts/respond.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia = window.matchMedia || (function(doc, undefined){ diff --git a/Samples/TripleAdd/Scripts/respond.min.js b/Samples/TripleAdd/Scripts/respond.min.js index a848137..94e308e 100644 --- a/Samples/TripleAdd/Scripts/respond.min.js +++ b/Samples/TripleAdd/Scripts/respond.min.js @@ -1,17 +1,3 @@ -/* NUGET: BEGIN LICENSE TEXT - * - * Microsoft grants you the right to use these script files for the sole - * purpose of either: (i) interacting through your browser with the Microsoft - * website or online service, subject to the applicable licensing or use - * terms; or (ii) using the files as included with a Microsoft product subject - * to that product's license terms. Microsoft reserves all other rights to the - * files not expressly granted by Microsoft, whether by implication, estoppel - * or otherwise. Insofar as a script file is dual licensed under GPL, - * Microsoft neither took the code under GPL nor distributes it thereunder but - * under the terms set out in this paragraph. All notices and licenses - * below are for informational purposes only. - * - * NUGET: END LICENSE TEXT */ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); diff --git a/Samples/TripleAdd/TripleAdd.csproj b/Samples/TripleAdd/TripleAdd.csproj index 8bd6905..1142271 100644 --- a/Samples/TripleAdd/TripleAdd.csproj +++ b/Samples/TripleAdd/TripleAdd.csproj @@ -25,6 +25,7 @@ + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib true @@ -44,11 +45,19 @@ 4 + + ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll + ..\..\Modbus.Net\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True + + ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + @@ -58,6 +67,27 @@ + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + @@ -67,54 +97,13 @@ - - True - ..\..\Modbus.Net\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - ..\..\Modbus.Net\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\..\Modbus.Net\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - True + ..\..\Modbus.Net\packages\WebGrease.1.5.2\lib\WebGrease.dll - - True - ..\..\Modbus.Net\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll - - - - - ..\..\Modbus.Net\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll - @@ -128,6 +117,8 @@ + + @@ -136,6 +127,10 @@ + + + + @@ -163,17 +158,11 @@ + - - - - - - - {fdca72ba-6d06-4de0-b873-c11c4ac853ad} @@ -214,7 +203,7 @@ - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + 此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 From c9e504a56f19236a9b95f56d65a3257427a120b3 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 17 May 2017 11:38:57 +0800 Subject: [PATCH 14/62] 2017-05-17 Update 2 Change Unittests --- Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 2 +- .../ModbusMultiStationTest.cs | 54 +++++++---- Tests/Modbus.Net.Tests/ModbusTest.cs | 63 +++++++------ Tests/Modbus.Net.Tests/SiemensTest.cs | 89 ++++++++++++------- 4 files changed, 130 insertions(+), 78 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index 5f6cbb2..95a751f 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -27,7 +27,7 @@ namespace Modbus.Net.Modbus /// /// Modbus基础Api入口 /// - public class ModbusUtility : BaseUtility, IIUtilityMethodTime + public class ModbusUtility : BaseUtility, IUtilityMethodTime { /// /// Modbus协议类型 diff --git a/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs b/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs index f86fac3..37bfa33 100644 --- a/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusMultiStationTest.cs @@ -22,7 +22,7 @@ namespace Modbus.Net.Tests } [TestMethod] - public async Task Get() + public async Task MultiStation() { var addresses = new List { @@ -85,56 +85,72 @@ namespace Modbus.Net.Tests _modbusRtuMachine1.GetAddresses = addresses.ToList(); _modbusRtuMachine2.GetAddresses = addresses.ToList(); - await _modbusRtuMachine1.SetDatasAsync(MachineSetDataType.CommunicationTag, new Dictionary() + Random r = new Random(); + var dic1 = new Dictionary() { { - "A1", 70 + "A1", r.Next(0, UInt16.MaxValue) }, { - "A2", 71 + "A2", r.Next(0, UInt16.MaxValue) }, { - "A3", 72 + "A3", r.Next(0, UInt16.MaxValue) }, { - "A4", 73 + "A4", r.Next(0, UInt16.MaxValue) }, { - "A5", 717870 + "A5", r.Next() }, { - "A6", 717871 + "A6", r.Next() }, - }); - await _modbusRtuMachine2.SetDatasAsync(MachineSetDataType.CommunicationTag, new Dictionary() + }; + + var dic2 = new Dictionary() { { - "A1", 74 + "A1", r.Next(0, UInt16.MaxValue) }, { - "A2", 75 + "A2", r.Next(0, UInt16.MaxValue) }, { - "A3", 76 + "A3", r.Next(0, UInt16.MaxValue) }, { - "A4", 77 + "A4", r.Next(0, UInt16.MaxValue) }, { - "A5", 717873 + "A5", r.Next() }, { - "A6", 717874 + "A6", r.Next() }, - }); + }; + + await _modbusRtuMachine1.SetDatasAsync(MachineSetDataType.CommunicationTag, dic1); + await _modbusRtuMachine2.SetDatasAsync(MachineSetDataType.CommunicationTag, dic2); + var ans = await _modbusRtuMachine1.GetDatasAsync(MachineGetDataType.CommunicationTag); var ans2 = await _modbusRtuMachine2.GetDatasAsync(MachineGetDataType.CommunicationTag); _modbusRtuMachine1.Disconnect(); _modbusRtuMachine2.Disconnect(); - Assert.AreEqual(ans["A1"].PlcValue, 70); - Assert.AreEqual(ans2["A1"].PlcValue, 74); + Assert.AreEqual(ans["A1"].PlcValue, dic1["A1"]); + Assert.AreEqual(ans2["A1"].PlcValue, dic2["A1"]); + Assert.AreEqual(ans["A2"].PlcValue, dic1["A2"]); + Assert.AreEqual(ans2["A2"].PlcValue, dic2["A2"]); + Assert.AreEqual(ans["A3"].PlcValue, dic1["A3"]); + Assert.AreEqual(ans2["A3"].PlcValue, dic2["A3"]); + Assert.AreEqual(ans["A4"].PlcValue, dic1["A4"]); + Assert.AreEqual(ans2["A4"].PlcValue, dic2["A4"]); + Assert.AreEqual(ans["A5"].PlcValue, dic1["A5"]); + Assert.AreEqual(ans2["A5"].PlcValue, dic2["A5"]); + Assert.AreEqual(ans["A6"].PlcValue, dic1["A6"]); + Assert.AreEqual(ans2["A6"].PlcValue, dic2["A6"]); } } } diff --git a/Tests/Modbus.Net.Tests/ModbusTest.cs b/Tests/Modbus.Net.Tests/ModbusTest.cs index 6e25dd6..b4b4833 100644 --- a/Tests/Modbus.Net.Tests/ModbusTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusTest.cs @@ -20,6 +20,8 @@ namespace Modbus.Net.Tests [TestMethod] public async Task ModbusCoilSingle() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -33,15 +35,17 @@ namespace Modbus.Net.Tests } }; - _modbusTcpMachine.GetAddresses = addresses; - await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.Address, new Dictionary() + var dic1 = new Dictionary() { { - "0X 1.0", 1 + "0X 1.0", r.Next(0, 2) } - }); + }; + + _modbusTcpMachine.GetAddresses = addresses; + await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.Address); - Assert.AreEqual(ans["0X 1.0"].PlcValue, 1); + Assert.AreEqual(ans["0X 1.0"].PlcValue, dic1["0X 1.0"]); } [TestMethod] @@ -89,6 +93,8 @@ namespace Modbus.Net.Tests [TestMethod] public async Task ModbusRegSingle() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -102,20 +108,24 @@ namespace Modbus.Net.Tests } }; - _modbusTcpMachine.GetAddresses = addresses; - await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.Address, new Dictionary() + var dic1 = new Dictionary() { { - "4X 1", 31125 + "4X 1", r.Next(0, UInt16.MaxValue) } - }); + }; + + _modbusTcpMachine.GetAddresses = addresses; + await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.Address); - Assert.AreEqual(ans["4X 1.0"].PlcValue, 31125); + Assert.AreEqual(ans["4X 1.0"].PlcValue, dic1["4X 1"]); } [TestMethod] public async Task ModbusRegMultiple() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -174,35 +184,38 @@ namespace Modbus.Net.Tests } }; - _modbusTcpMachine.GetAddresses = addresses; - await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, new Dictionary() + var dic1 = new Dictionary() { { - "A1", 70 + "A1", r.Next(0, UInt16.MaxValue) }, { - "A2", 71 + "A2", r.Next(0, UInt16.MaxValue) }, { - "A3", 72 + "A3", r.Next(0, UInt16.MaxValue) }, { - "A4", 73 + "A4", r.Next(0, UInt16.MaxValue) }, { - "A5", 717870 + "A5", r.Next() }, { - "A6", 717871 + "A6", r.Next() }, - }); + }; + + _modbusTcpMachine.GetAddresses = addresses; + await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, dic1); + var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.CommunicationTag); - Assert.AreEqual(ans["A1"].PlcValue, 70); - Assert.AreEqual(ans["A2"].PlcValue, 71); - Assert.AreEqual(ans["A3"].PlcValue, 72); - Assert.AreEqual(ans["A4"].PlcValue, 73); - Assert.AreEqual(ans["A5"].PlcValue, 717870); - Assert.AreEqual(ans["A6"].PlcValue, 717871); + Assert.AreEqual(ans["A1"].PlcValue, dic1["A1"]); + Assert.AreEqual(ans["A2"].PlcValue, dic1["A2"]); + Assert.AreEqual(ans["A3"].PlcValue, dic1["A3"]); + Assert.AreEqual(ans["A4"].PlcValue, dic1["A4"]); + Assert.AreEqual(ans["A5"].PlcValue, dic1["A5"]); + Assert.AreEqual(ans["A6"].PlcValue, dic1["A6"]); } } } diff --git a/Tests/Modbus.Net.Tests/SiemensTest.cs b/Tests/Modbus.Net.Tests/SiemensTest.cs index 313595b..6d4b9af 100644 --- a/Tests/Modbus.Net.Tests/SiemensTest.cs +++ b/Tests/Modbus.Net.Tests/SiemensTest.cs @@ -21,6 +21,8 @@ namespace Modbus.Net.Tests [TestMethod] public async Task SiemensCoilSingle() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -34,15 +36,18 @@ namespace Modbus.Net.Tests } }; - _siemensTcpMachine.GetAddresses = addresses; - await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, new Dictionary() + var dic1 = new Dictionary() { { - "Q 0.0", 1 + "Q 0.0", r.Next(0, 2) } - }); + }; + + _siemensTcpMachine.GetAddresses = addresses; + await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + var ans = await _siemensTcpMachine.GetDatasAsync(MachineGetDataType.Address); - Assert.AreEqual(ans["Q 0.0"].PlcValue, 1); + Assert.AreEqual(ans["Q 0.0"].PlcValue, dic1["Q 0.0"]); } [TestMethod] @@ -69,6 +74,8 @@ namespace Modbus.Net.Tests [TestMethod] public async Task SiemensMSingle() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -84,19 +91,23 @@ namespace Modbus.Net.Tests _siemensTcpMachine.GetAddresses = addresses; - await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, new Dictionary() + var dic1 = new Dictionary() { { - "M 0", 31125 + "M 0", r.Next(0, UInt16.MaxValue) } - }); + }; + + await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); var ans = await _siemensTcpMachine.GetDatasAsync(MachineGetDataType.Address); - Assert.AreEqual(ans["M 0.0"].PlcValue, 31125); + Assert.AreEqual(ans["M 0.0"].PlcValue, dic1["M 0"]); } [TestMethod] public async Task SiemensMSingleBool() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -112,19 +123,24 @@ namespace Modbus.Net.Tests _siemensTcpMachine.GetAddresses = addresses; - await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, new Dictionary() + var dic1 = new Dictionary() { { - "M 0.0", 1 + "M 0.0", r.Next(0, 2) } - }); + }; + + await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + var ans = await _siemensTcpMachine.GetDatasAsync(MachineGetDataType.Address); - Assert.AreEqual(ans["M 0.0"].PlcValue, 1); + Assert.AreEqual(ans["M 0.0"].PlcValue, dic1["M 0.0"]); } [TestMethod] public async Task SiemensDbSingle() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -138,20 +154,25 @@ namespace Modbus.Net.Tests } }; - _siemensTcpMachine.GetAddresses = addresses; - await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, new Dictionary() + var dic1 = new Dictionary() { { - "DB2 0.0", 31125 + "DB2 0.0", r.Next(0, UInt16.MaxValue) } - }); + }; + + _siemensTcpMachine.GetAddresses = addresses; + await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + var ans = await _siemensTcpMachine.GetDatasAsync(MachineGetDataType.Address); - Assert.AreEqual(ans["DB2 0.0"].PlcValue, 31125); + Assert.AreEqual(ans["DB2 0.0"].PlcValue, dic1["DB2 0.0"]); } [TestMethod] public async Task SiemensDbMultiple() { + Random r = new Random(); + var addresses = new List { new AddressUnit @@ -210,35 +231,37 @@ namespace Modbus.Net.Tests } }; - _siemensTcpMachine.GetAddresses = addresses; - await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, new Dictionary() + var dic1 = new Dictionary() { { - "A1", 70 + "A1", r.Next(0, UInt16.MaxValue) }, { - "A2", 71 + "A2", r.Next(0, UInt16.MaxValue) }, { - "A3", 72 + "A3", r.Next(0, UInt16.MaxValue) }, { - "A4", 73 + "A4", r.Next(0, UInt16.MaxValue) }, { - "A5", 717870 + "A5", r.Next() }, { - "A6", 717871 + "A6", r.Next() }, - }); + }; + + _siemensTcpMachine.GetAddresses = addresses; + await _siemensTcpMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, dic1); var ans = await _siemensTcpMachine.GetDatasAsync(MachineGetDataType.CommunicationTag); - Assert.AreEqual(ans["A1"].PlcValue, 70); - Assert.AreEqual(ans["A2"].PlcValue, 71); - Assert.AreEqual(ans["A3"].PlcValue, 72); - Assert.AreEqual(ans["A4"].PlcValue, 73); - Assert.AreEqual(ans["A5"].PlcValue, 717870); - Assert.AreEqual(ans["A6"].PlcValue, 717871); + Assert.AreEqual(ans["A1"].PlcValue, dic1["A1"]); + Assert.AreEqual(ans["A2"].PlcValue, dic1["A2"]); + Assert.AreEqual(ans["A3"].PlcValue, dic1["A3"]); + Assert.AreEqual(ans["A4"].PlcValue, dic1["A4"]); + Assert.AreEqual(ans["A5"].PlcValue, dic1["A5"]); + Assert.AreEqual(ans["A6"].PlcValue, dic1["A6"]); } } } From 3c6f18dc694a783bda06fee08345f3c88ca1f789 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 17 May 2017 14:59:23 +0800 Subject: [PATCH 15/62] Add serilog --- .../Modbus.Net.Core/Modbus.Net.Core.csproj | 1 + .../Modbus.Net.Modbus.csproj | 4 - .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 1 - .../Modbus.Net.Siemens.csproj | 4 - Modbus.Net/Modbus.Net/ComConnector.cs | 246 +++++++++++------- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 7 + Modbus.Net/src/Base.Common/TcpConnector.cs | 74 +++--- 7 files changed, 198 insertions(+), 139 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index c1c1818..0578162 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -56,6 +56,7 @@ + diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index fef1838..d0c29f2 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -23,10 +23,6 @@ bin\Debug\net45\Modbus.Net.Modbus.xml - - - - diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index 34e799c..3f38142 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -25,7 +25,6 @@ - diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index b863ece..3c27504 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -22,10 +22,6 @@ bin\Debug\net45\Modbus.Net.Siemens.xml - - - - diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs index 7802356..3454532 100644 --- a/Modbus.Net/Modbus.Net/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/ComConnector.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Serilog; namespace Modbus.Net { @@ -65,6 +66,10 @@ namespace Modbus.Net /// private bool m_disposed; + private int _sendCount; + private int _receiveCount; + private int _errorCount; + /// /// 构造器 /// @@ -135,47 +140,37 @@ namespace Modbus.Net /// /// 串口数据缓冲 /// 串口数据缓冲空间大小 - /// 设置串口读放弃时间 - /// 字节间隔最大时间 + /// 设置串口读放弃时间 + /// 字节间隔最大时间 /// 串口实际读入数据个数 - public int ReadComm(out byte[] readBuf, int bufRoom, int HowTime, int ByteTime) - { - //throw new System.NotImplementedException(); + public int ReadComm(out byte[] readBuf, int bufRoom, int howTime, int byteTime) + { readBuf = new byte[1023]; Array.Clear(readBuf, 0, readBuf.Length); - int nReadLen, nBytelen; if (SerialPort.IsOpen == false) return -1; - nBytelen = 0; - SerialPort.ReadTimeout = HowTime; + var nBytelen = 0; + SerialPort.ReadTimeout = howTime; - - try + while (SerialPort.BytesToRead > 0) { - while (SerialPort.BytesToRead > 0) + readBuf[nBytelen] = (byte) SerialPort.ReadByte(); + var bTmp = new byte[bufRoom]; + Array.Clear(bTmp, 0, bTmp.Length); + + var nReadLen = ReadBlock(bTmp, bufRoom, byteTime); + + if (nReadLen > 0) { - readBuf[nBytelen] = (byte) SerialPort.ReadByte(); - var bTmp = new byte[bufRoom]; - Array.Clear(bTmp, 0, bTmp.Length); - - nReadLen = ReadBlock(bTmp, bufRoom, ByteTime); - - if (nReadLen > 0) - { - Array.Copy(bTmp, 0, readBuf, nBytelen + 1, nReadLen); - nBytelen += 1 + nReadLen; - } - - else if (nReadLen == 0) - { - nBytelen += 1; - } + Array.Copy(bTmp, 0, readBuf, nBytelen + 1, nReadLen); + nBytelen += 1 + nReadLen; + } + + else if (nReadLen == 0) + { + nBytelen += 1; } - } - catch (Exception ex) - { - throw new Exception(ex.Message); } return nBytelen; @@ -184,31 +179,23 @@ namespace Modbus.Net /// /// 串口同步读(阻塞方式读串口,直到串口缓冲区中没有数据,靠字符间间隔超时确定没有数据) /// - /// 串口数据缓冲 - /// 串口数据缓冲空间大小 - /// 字节间隔最大时间 + /// 串口数据缓冲 + /// 串口数据缓冲空间大小 + /// 字节间隔最大时间 /// 从串口实际读入的字节个数 - public int ReadBlock(byte[] ReadBuf, int ReadRoom, int ByteTime) + public int ReadBlock(byte[] readBuf, int readRoom, int byteTime) { - sbyte nBytelen; - //long nByteRead; - if (SerialPort.IsOpen == false) return 0; - nBytelen = 0; - SerialPort.ReadTimeout = ByteTime; + sbyte nBytelen = 0; + SerialPort.ReadTimeout = byteTime; - while (nBytelen < ReadRoom - 1 && SerialPort.BytesToRead > 0) - try - { - ReadBuf[nBytelen] = (byte) SerialPort.ReadByte(); - nBytelen++; // add one - } - catch (Exception ex) - { - throw new Exception(ex.Message); - } - ReadBuf[nBytelen] = 0x00; + while (nBytelen < readRoom - 1 && SerialPort.BytesToRead > 0) + { + readBuf[nBytelen] = (byte) SerialPort.ReadByte(); + nBytelen++; // add one + } + readBuf[nBytelen] = 0x00; return nBytelen; } @@ -216,72 +203,63 @@ namespace Modbus.Net /// /// 字符数组转字符串16进制 /// - /// 二进制字节 + /// 二进制字节 /// 类似"01 02 0F" - public static string ByteToString(byte[] InBytes) + public static string ByteToString(byte[] inBytes) { - var StringOut = ""; - foreach (var InByte in InBytes) - StringOut = StringOut + string.Format("{0:X2}", InByte) + " "; + var stringOut = ""; + foreach (var inByte in inBytes) + stringOut = stringOut + $"{inByte:X2}" + " "; - return StringOut.Trim(); + return stringOut.Trim(); } /// /// strhex 转字节数组 /// - /// 类似"01 02 0F" 用空格分开的 + /// 类似"01 02 0F" 用空格分开的 /// - public static byte[] StringToByte(string InString) + public static byte[] StringToByte(string inString) { - string[] ByteStrings; - ByteStrings = InString.Split(" ".ToCharArray()); - byte[] ByteOut; - ByteOut = new byte[ByteStrings.Length]; - for (var i = 0; i <= ByteStrings.Length - 1; i++) - ByteOut[i] = byte.Parse(ByteStrings[i], NumberStyles.HexNumber); - return ByteOut; + var byteStrings = inString.Split(" ".ToCharArray()); + var byteOut = new byte[byteStrings.Length]; + for (var i = 0; i <= byteStrings.Length - 1; i++) + byteOut[i] = byte.Parse(byteStrings[i], NumberStyles.HexNumber); + return byteOut; } /// /// strhex 转字节数组 /// - /// 类似"01 02 0F" 中间无空格 + /// 类似"01 02 0F" 中间无空格 /// - public static byte[] StringToByte_2(string InString) + public static byte[] StringToByte_2(string inString) { - byte[] ByteOut; - InString = InString.Replace(" ", ""); - try - { - var ByteStrings = new string[InString.Length / 2]; - var j = 0; - for (var i = 0; i < ByteStrings.Length; i++) - { - ByteStrings[i] = InString.Substring(j, 2); - j += 2; - } + inString = inString.Replace(" ", ""); - ByteOut = new byte[ByteStrings.Length]; - for (var i = 0; i <= ByteStrings.Length - 1; i++) - ByteOut[i] = byte.Parse(ByteStrings[i], NumberStyles.HexNumber); - } - catch (Exception ex) + var byteStrings = new string[inString.Length / 2]; + var j = 0; + for (var i = 0; i < byteStrings.Length; i++) { - throw new Exception(ex.Message); + byteStrings[i] = inString.Substring(j, 2); + j += 2; } - return ByteOut; + var byteOut = new byte[byteStrings.Length]; + for (var i = 0; i <= byteStrings.Length - 1; i++) + byteOut[i] = byte.Parse(byteStrings[i], NumberStyles.HexNumber); + + return byteOut; } /// /// 字符串 转16进制字符串 /// - /// unico + /// unico /// 类似“01 0f” - public static string Str_To_0X(string InString) + public static string Str_To_0X(string inString) { - return ByteToString(Encoding.Default.GetBytes(InString)); + return ByteToString(Encoding.Default.GetBytes(inString)); } /// @@ -310,10 +288,12 @@ namespace Modbus.Net //ignore } SerialPort.Dispose(); + Log.Information("Com interface {Com} Disposed", _com); Connectors[_com] = null; Connectors.Remove(_com); } Linkers.Remove(_slave); + Log.Information("Com connector {ConnectionToken} Removed", ConnectionToken); } m_disposed = true; } @@ -364,10 +344,12 @@ namespace Modbus.Net if (!Linkers.ContainsKey(_slave)) Linkers.Add(_slave, _com); SerialPort.Open(); + Log.Information("Com client {ConnectionToken} connect success", ConnectionToken); return true; } - catch (Exception) + catch (Exception e) { + Log.Error(e, "Com client {ConnectionToken} connect error", ConnectionToken); return false; } } @@ -391,12 +373,15 @@ namespace Modbus.Net try { Dispose(); + Log.Information("Com client {ConnectionToken} disconnect success", ConnectionToken); return true; } - catch + catch (Exception e) { + Log.Error(e, "Com client {ConnectionToken} disconnect error", ConnectionToken); return false; } + Log.Error(new Exception("Linkers or Connectors Dictionary not found"), "Com client {ConnectionToken} disconnect error", ConnectionToken); return false; } @@ -438,19 +423,48 @@ namespace Modbus.Net { SerialPort.Open(); } - catch (Exception) + catch (Exception err) { + Log.Error(err, "Com client {ConnectionToken} open error", ConnectionToken); Dispose(); SerialPort.Open(); } + + byte[] returnBytes; + lock (SerialPort.Lock) { - SerialPort.Write(sendbytes, 0, sendbytes.Length); + try + { + Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); + Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); + SerialPort.Write(sendbytes, 0, sendbytes.Length); + } + catch (Exception err) + { + Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken); + return null; + } + RefreshSendCount(); + + try + { + returnBytes = ReadMsg(); + Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, returnBytes.Length); + Log.Verbose("Com client {ConnectionToken} receive msg: {SendBytes}", ConnectionToken, returnBytes); + } + catch (Exception e) + { + Log.Error(e, "Com client {ConnectionToken} read msg error", ConnectionToken); + return null; + } + RefreshReceiveCount(); } - return ReadMsg(); + return returnBytes; } - catch + catch (Exception err) { + Log.Error(err, "Com client {ConnectionToken} read error", ConnectionToken); Dispose(); return null; } @@ -480,19 +494,33 @@ namespace Modbus.Net { SerialPort.Open(); } - catch (Exception) + catch (Exception err) { + Log.Error(err, "Com client {ConnectionToken} open error", ConnectionToken); Dispose(); SerialPort.Open(); } lock (SerialPort.Lock) { - SerialPort.Write(sendbytes, 0, sendbytes.Length); + try + { + Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); + Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); + SerialPort.Write(sendbytes, 0, sendbytes.Length); + } + catch (Exception err) + { + Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken); + Dispose(); + return false; + } + RefreshSendCount(); } return true; } - catch (Exception) + catch (Exception err) { + Log.Error(err, "Com client {ConnectionToken} reopen error", ConnectionToken); return false; } } @@ -511,13 +539,33 @@ namespace Modbus.Net Array.Copy(data, 0, returndata, 0, i); return returndata; } - catch (Exception) + catch (Exception e) { + Log.Error(e, "Com client {ConnectionToken} read error", ConnectionToken); + RefreshErrorCount(); Dispose(); return null; } } #endregion + + private void RefreshSendCount() + { + _sendCount++; + Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); + } + + private void RefreshReceiveCount() + { + _receiveCount++; + Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + } + + private void RefreshErrorCount() + { + _errorCount++; + Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + } } } \ 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 00e6daa..ef209ac 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -52,6 +52,7 @@ + @@ -60,4 +61,10 @@ + + + Component + + + \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/TcpConnector.cs b/Modbus.Net/src/Base.Common/TcpConnector.cs index 8317870..8f1a56e 100644 --- a/Modbus.Net/src/Base.Common/TcpConnector.cs +++ b/Modbus.Net/src/Base.Common/TcpConnector.cs @@ -2,6 +2,7 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using Serilog; namespace Modbus.Net { @@ -34,12 +35,15 @@ namespace Modbus.Net private readonly string _host; private readonly int _port; - // 2MB 的接收缓冲区,目的是一次接收完服务器发回的消息 + /// + /// 1MB 的接收缓冲区 + /// private readonly byte[] _receiveBuffer = new byte[1024]; - private int _errorCount; - private int _receiveCount; private int _sendCount; + private int _receiveCount; + private int _errorCount; + private TcpClient _socketClient; private int _timeoutTime; @@ -69,7 +73,7 @@ namespace Modbus.Net /// public int TimeoutTime { - get { return _timeoutTime; } + get => _timeoutTime; set { _timeoutTime = value; @@ -111,9 +115,14 @@ namespace Modbus.Net if (_socketClient != null) { CloseClientSocket(); - _socketClient.Client.Dispose(); +#if NET40 || NET45 || NET451 || NET452 + _socketClient.Close(); +#else + _socketClient.Dispose(); +#endif + Log.Debug("Tcp client {ConnectionToken} Disposed", ConnectionToken); } - m_disposed = true; + m_disposed = true; } } @@ -159,19 +168,19 @@ namespace Modbus.Net } catch (Exception e) { - AddInfo("client connected exception: " + e.Message); + Log.Error(e, "Tcp client {ConnectionToken} connect error", ConnectionToken); } if (_socketClient.Connected) { - AddInfo("client connected."); + Log.Information("Tcp client {ConnectionToken} connected", ConnectionToken); return true; } - AddInfo("connect failed."); + Log.Error("Tcp client {ConnectionToken} connect failed.", ConnectionToken); return false; } catch (Exception err) { - AddInfo("client connect exception: " + err.Message); + Log.Error(err, "Tcp client {ConnectionToken} connect exception", ConnectionToken); return false; } } @@ -187,17 +196,13 @@ namespace Modbus.Net try { -#if NET40 || NET45 || NET451 || NET452 - _socketClient.Close(); -#else - _socketClient.Dispose(); -#endif - AddInfo("client disconnected successfully."); + Dispose(); + Log.Information("Tcp client {ConnectionToken} disconnected successfully", ConnectionToken); return true; } catch (Exception err) { - AddInfo("client disconnected exception: " + err.Message); + Log.Error(err, "Tcp client {ConnectionToken} disconnected exception", ConnectionToken); return false; } finally @@ -206,11 +211,6 @@ namespace Modbus.Net } } - private void AddInfo(string message) - { - Console.WriteLine(message); - } - /// /// 发送数据,不需要返回任何值 /// @@ -236,15 +236,18 @@ namespace Modbus.Net await ConnectAsync(); var stream = _socketClient.GetStream(); + + Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); + Log.Verbose("Tcp client {ConnectionToken} send text = {Datagram}", ConnectionToken, datagram); await stream.WriteAsync(datagram, 0, datagram.Length); RefreshSendCount(); - //this.AddInfo("send text len = " + datagramText.Length.ToString()); + return true; } catch (Exception err) { - AddInfo("send exception: " + err.Message); + Log.Error(err, "Tcp client {ConnectionToken} send exception", ConnectionToken); CloseClientSocket(); return false; } @@ -275,16 +278,22 @@ namespace Modbus.Net await ConnectAsync(); var stream = _socketClient.GetStream(); + + Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); + Log.Verbose("Tcp client {ConnectionToken} send: {Datagram}", ConnectionToken, datagram); await stream.WriteAsync(datagram, 0, datagram.Length); - + RefreshSendCount(); - //this.AddInfo("send text len = " + datagramText.Length.ToString()); - return await ReceiveAsync(stream); + var receiveBytes = await ReceiveAsync(stream); + Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, receiveBytes.Length); + Log.Verbose("Tcp client {ConnectionToken} receive: {Datagram}", ConnectionToken, receiveBytes); + + return receiveBytes; } catch (Exception err) { - AddInfo("send exception: " + err.Message); + Log.Error(err, "Tcp client {ConnectionToken} send exception", ConnectionToken); CloseClientSocket(); return null; } @@ -308,7 +317,7 @@ namespace Modbus.Net } catch (Exception err) { - AddInfo("receive exception: " + err.Message); + Log.Error(err, "Tcp client {ConnectionToken} receive exception", ConnectionToken); CloseClientSocket(); return null; } @@ -323,7 +332,7 @@ namespace Modbus.Net var replyMessage = new byte[len]; Array.Copy(_receiveBuffer, replyMessage, len); - //this.AddInfo("reply: " + replyMesage); + Log.Verbose("Tcp client {ConnectionToken} reply: {replyMessage}",ConnectionToken, replyMessage); RefreshReceiveCount(); if (len <= 0) @@ -335,16 +344,19 @@ namespace Modbus.Net private void RefreshSendCount() { _sendCount++; + Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); } private void RefreshReceiveCount() { _receiveCount++; + Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); } private void RefreshErrorCount() { _errorCount++; + Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); } private void CloseClientSocket() @@ -358,7 +370,7 @@ namespace Modbus.Net } catch (Exception ex) { - AddInfo("client close exception: " + ex.Message); + Log.Error(ex, "Tcp client {ConnectionToken} client close exception", ConnectionToken); } } } From ba56c5be1b170c47ac50d67ce88c206169834f95 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 17 May 2017 18:01:30 +0800 Subject: [PATCH 16/62] 2017-05-17 Update 3 Implement log system and add comments --- .../AddressFormaterModbus.cs | 26 ++ .../AddressTranslatorModbus.cs | 28 ++ .../Modbus.Net.Modbus/ModbusAsciiProtocal.cs | 13 + .../ModbusAsciiProtocalLinker.cs | 11 + Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs | 38 ++ .../Modbus.Net.Modbus/ModbusProtocal.cs | 328 +++++++++++++++++- .../ModbusProtocalLinkerBytesExtend.cs | 36 ++ .../Modbus.Net.Modbus/ModbusRtuProtocal.cs | 13 + .../ModbusRtuProtocalLinker.cs | 11 + .../Modbus.Net.Modbus/ModbusTcpProtocal.cs | 21 ++ .../ModbusTcpProtocalLinker.cs | 15 + Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 47 ++- Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 14 +- Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 5 +- .../AddressFormaterSiemens.cs | 26 ++ .../AddressTranslatorSiemens.cs | 34 ++ .../Modbus.Net.Siemens/SiemensMachine.cs | 38 ++ .../Modbus.Net.Siemens/SiemensPpiProtocal.cs | 37 +- .../SiemensPpiProtocalLinker.cs | 20 ++ .../SiemensProtocalLinkerBytesExtend.cs | 20 ++ .../Modbus.Net.Siemens/SiemensTcpProtocal.cs | 66 ++++ .../SiemensTcpProtocalLinker.cs | 14 + .../Modbus.Net.Siemens/SiemensUtility.cs | 62 +++- Modbus.Net/Modbus.Net/ComConnector.cs | 66 ++-- .../src/Base.Common/AddressTranslator.cs | 4 +- Modbus.Net/src/Base.Common/BaseConnector.cs | 1 - Modbus.Net/src/Base.Common/BaseMachine.cs | 16 +- Modbus.Net/src/Base.Common/BaseProtocal.cs | 3 +- Modbus.Net/src/Base.Common/BaseUtility.cs | 12 +- Modbus.Net/src/Base.Common/TaskManager.cs | 5 +- Modbus.Net/src/Base.Common/TcpConnector.cs | 19 +- .../src/Base.Common/TcpProtocalLinker.cs | 4 +- Modbus.Net/src/Base.Common/TypeExtensions.cs | 2 +- Modbus.Net/src/Base.Common/ValueHelper.cs | 14 +- 34 files changed, 987 insertions(+), 82 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/AddressFormaterModbus.cs b/Modbus.Net/Modbus.Net.Modbus/AddressFormaterModbus.cs index ffe8813..1de8840 100644 --- a/Modbus.Net/Modbus.Net.Modbus/AddressFormaterModbus.cs +++ b/Modbus.Net/Modbus.Net.Modbus/AddressFormaterModbus.cs @@ -5,11 +5,24 @@ /// public class AddressFormaterNA200H : AddressFormater { + /// + /// 格式化地址 + /// + /// 地址区域 + /// 地址 + /// 格式化的地址字符串 public override string FormatAddress(string area, int address) { return area + " " + address; } + /// + /// 格式化地址 + /// + /// 地址区域 + /// 地址 + /// 比特位地址 + /// 格式化的地址字符串 public override string FormatAddress(string area, int address, int subAddress) { return area + " " + address + "." + subAddress; @@ -21,11 +34,24 @@ /// public class AddressFormaterModbus : AddressFormater { + /// + /// 格式化地址 + /// + /// 地址区域 + /// 地址 + /// 格式化的地址字符串 public override string FormatAddress(string area, int address) { return area + " " + address; } + /// + /// 格式化地址 + /// + /// 地址区域 + /// 地址 + /// 比特位地址 + /// 格式化的地址字符串 public override string FormatAddress(string area, int address, int subAddress) { return area + " " + address + "." + subAddress; diff --git a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs index 3edcd80..b4b6ec4 100644 --- a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs +++ b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs @@ -23,6 +23,9 @@ namespace Modbus.Net.Modbus /// protected Dictionary WriteFunctionCodeDictionary; + /// + /// 构造器 + /// public AddressTranslatorNA200H() { TransDictionary = new Dictionary @@ -154,6 +157,12 @@ namespace Modbus.Net.Modbus }; } + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 翻译后的地址 public override AddressDef AddressTranslate(string address, bool isRead) { address = address.ToUpper(); @@ -188,6 +197,11 @@ namespace Modbus.Net.Modbus }; } + /// + /// 获取区域中的单个地址占用的字节长度 + /// + /// 区域名称 + /// 字节长度 public override double GetAreaByteLength(string area) { return ReadFunctionCodeDictionary[area].AreaWidth; @@ -209,6 +223,9 @@ namespace Modbus.Net.Modbus /// protected Dictionary WriteFunctionCodeDictionary; + /// + /// 构造器 + /// public AddressTranslatorModbus() { ReadFunctionCodeDictionary = new Dictionary @@ -259,6 +276,12 @@ namespace Modbus.Net.Modbus }; } + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 翻译后的地址 public override AddressDef AddressTranslate(string address, bool isRead) { address = address.ToUpper(); @@ -293,6 +316,11 @@ namespace Modbus.Net.Modbus }; } + /// + /// 获取区域中的单个地址占用的字节长度 + /// + /// 区域名称 + /// 字节长度 public override double GetAreaByteLength(string area) { return ReadFunctionCodeDictionary[area].AreaWidth; diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs index bf93d71..22c5b58 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs @@ -7,11 +7,24 @@ namespace Modbus.Net.Modbus /// public class ModbusAsciiProtocal : ModbusProtocal { + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 + /// 端格式 public ModbusAsciiProtocal(byte slaveAddress, byte masterAddress, Endian endian) : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, endian) { } + /// + /// 构造函数 + /// + /// 串口地址 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusAsciiProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs index a37c55a..1b45171 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs @@ -8,13 +8,24 @@ namespace Modbus.Net.Modbus /// public class ModbusAsciiProtocalLinker : ComProtocalLinker { + /// + /// 构造函数 + /// + /// 串口地址 + /// 从站号 public ModbusAsciiProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { } + /// + /// 校验返回数据是否正确 + /// + /// 返回的数据 + /// 校验是否正确 public override bool? CheckRight(byte[] content) { + //ProtocalLinker不会返回null if (!base.CheckRight(content).Value) return false; //CRC校验失败 var contentString = Encoding.ASCII.GetString(content); diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs index 450a12d..85b2d81 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs @@ -9,6 +9,16 @@ namespace Modbus.Net.Modbus public class ModbusMachine : BaseMachine where TKey : IEquatable where TUnitKey : IEquatable { + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 读写的地址 + /// 是否保持连接 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusMachine(ModbusType connectionType, string connectionString, IEnumerable> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) @@ -20,6 +30,15 @@ namespace Modbus.Net.Modbus AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 读写的地址 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusMachine(ModbusType connectionType, string connectionString, IEnumerable> getAddresses, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) @@ -33,6 +52,16 @@ namespace Modbus.Net.Modbus /// public class ModbusMachine : BaseMachine { + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 读写的地址 + /// 是否保持连接 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusMachine(ModbusType connectionType, string connectionString, IEnumerable getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) @@ -44,6 +73,15 @@ namespace Modbus.Net.Modbus AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 读写的地址 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusMachine(ModbusType connectionType, string connectionString, IEnumerable getAddresses, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs index f261609..9f2a763 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs @@ -9,7 +9,14 @@ namespace Modbus.Net.Modbus /// internal enum ModbusProtocalVariableFunctionCode : byte { + /// + /// 读变量 + /// ReadVariable = 20, + + /// + /// 写变量 + /// WriteVariable = 21 } @@ -18,7 +25,14 @@ namespace Modbus.Net.Modbus /// public enum ModbusProtocalTimeFunctionCode : byte { + /// + /// 读时间 + /// GetSystemTime = 3, + + /// + /// 写时间 + /// SetSystemTime = 16 } @@ -27,9 +41,24 @@ namespace Modbus.Net.Modbus /// public enum ModbusProtocalReadDataFunctionCode : byte { + /// + /// 读线圈 + /// ReadCoilStatus = 1, + + /// + /// 读输入线圈 + /// ReadInputStatus = 2, + + /// + /// 读保持寄存器 + /// ReadHoldRegister = 3, + + /// + /// 读输入寄存器 + /// ReadInputRegister = 4 } @@ -38,7 +67,24 @@ namespace Modbus.Net.Modbus /// internal enum ModbusProtocalWriteDataFunctionCode : byte { + /// + /// 写单个线圈 + /// + WriteSingleCoil = 5, + + /// + /// 写单个寄存器 + /// + WriteSingleRegister = 6, + + /// + /// 写多个线圈 + /// WriteMultiCoil = 15, + + /// + /// 写多个寄存器 + /// WriteMultiRegister = 16 } @@ -47,16 +93,30 @@ namespace Modbus.Net.Modbus /// public abstract class ModbusProtocal : BaseProtocal { + /// + /// 构造函数 + /// + /// 从站地址 + /// 主站地址 + /// 端格式 protected ModbusProtocal(byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { } + /// + /// 连接 + /// + /// 是否连接成功 public override bool Connect() { return ProtocalLinker.Connect(); } + /// + /// 连接 + /// + /// 是否连接成功 public override async Task ConnectAsync() { return await ProtocalLinker.ConnectAsync(); @@ -65,8 +125,18 @@ namespace Modbus.Net.Modbus #region 读PLC数据 + /// + /// 读数据输入 + /// public class ReadDataModbusInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站地址 + /// 开始地址 + /// 读取个数 + /// 地址翻译器 public ReadDataModbusInputStruct(byte slaveAddress, string startAddress, ushort getCount, AddressTranslator addressTranslator) { @@ -78,17 +148,39 @@ namespace Modbus.Net.Modbus (ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); } + /// + /// 从站地址 + /// public byte SlaveAddress { get; } + /// + /// 功能码 + /// public byte FunctionCode { get; } + /// + /// 开始地址 + /// public ushort StartAddress { get; } + /// + /// 获取个数 + /// public ushort GetCount { get; } } + /// + /// 读数据输出 + /// public class ReadDataModbusOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 功能码 + /// 数据个数 + /// 读取的数据值 public ReadDataModbusOutputStruct(byte slaveAddress, byte functionCode, int dataCount, byte[] dataValue) { @@ -98,17 +190,37 @@ namespace Modbus.Net.Modbus DataValue = dataValue.Clone() as byte[]; } + /// + /// 从站号 + /// public byte SlaveAddress { get; private set; } + /// + /// 功能码 + /// public byte FunctionCode { get; private set; } + /// + /// 数据个数 + /// public int DataCount { get; private set; } + /// + /// 数据值 + /// public byte[] DataValue { get; private set; } } + /// + /// 读数据协议 + /// public class ReadDataModbusProtocal : ProtocalUnit { + /// + /// 格式化 + /// + /// 读取参数 + /// 读取数据的协议核心 public override byte[] Format(IInputStruct message) { var r_message = (ReadDataModbusInputStruct) message; @@ -116,6 +228,12 @@ namespace Modbus.Net.Modbus r_message.StartAddress, r_message.GetCount); } + /// + /// 反格式化 + /// + /// 设备返回的信息 + /// 当前反格式化的位置 + /// 反格式化的信息 public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) { var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref pos); @@ -131,8 +249,19 @@ namespace Modbus.Net.Modbus #region 写PLC数据 + /// + /// 写数据输入 + /// public class WriteDataModbusInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 开始地址 + /// 写入的数据 + /// 地址翻译器 + /// 端格式 public WriteDataModbusInputStruct(byte slaveAddress, string startAddress, object[] writeValue, AddressTranslator addressTranslator, Endian endian) { @@ -147,21 +276,49 @@ namespace Modbus.Net.Modbus WriteValue = writeByteValue; } + /// + /// 从站号 + /// public byte SlaveAddress { get; } + /// + /// 功能码 + /// public byte FunctionCode { get; } + /// + /// 开始地址 + /// public ushort StartAddress { get; } + /// + /// 写入个数 + /// public ushort WriteCount { get; } + /// + /// 写入字节个数 + /// public byte WriteByteCount { get; } + /// + /// 写入的数据 + /// public byte[] WriteValue { get; } } + /// + /// 写数据输出 + /// public class WriteDataModbusOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 功能码 + /// 开始地址 + /// 写入个数 public WriteDataModbusOutputStruct(byte slaveAddress, byte functionCode, ushort startAddress, ushort writeCount) { @@ -171,20 +328,37 @@ namespace Modbus.Net.Modbus WriteCount = writeCount; } + /// + /// 从站号 + /// public byte SlaveAddress { get; private set; } + /// + /// 功能码 + /// public byte FunctionCode { get; private set; } + /// + /// 开始地址 + /// public ushort StartAddress { get; private set; } + /// + /// 写入个数 + /// public ushort WriteCount { get; private set; } } /// - /// 写多个寄存器状态 + /// 写多个寄存器协议 /// public class WriteDataModbusProtocal : ProtocalUnit { + /// + /// 格式化 + /// + /// 写寄存器参数 + /// 写寄存器协议核心 public override byte[] Format(IInputStruct message) { var r_message = (WriteDataModbusInputStruct) message; @@ -194,6 +368,12 @@ namespace Modbus.Net.Modbus return formattingBytes; } + /// + /// 反格式化 + /// + /// 设备返回的信息 + /// 当前反格式化的位置 + /// 反格式化的信息 public override IOutputStruct Unformat(byte[] messageBytes, ref int flag) { var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); @@ -209,8 +389,15 @@ namespace Modbus.Net.Modbus #region 读PLC时间 + /// + /// 读时间输入 + /// public class GetSystemTimeModbusInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站号 public GetSystemTimeModbusInputStruct(byte slaveAddress) { SlaveAddress = slaveAddress; @@ -219,17 +406,45 @@ namespace Modbus.Net.Modbus GetCount = 5; } + /// + /// 从站号 + /// public byte SlaveAddress { get; } + /// + /// 功能码 + /// public byte FunctionCode { get; } + /// + /// 开始地址 + /// public ushort StartAddress { get; } + /// + /// 获取个数 + /// public ushort GetCount { get; } } + /// + /// 读时间输出 + /// public class GetSystemTimeModbusOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 功能码 + /// 写入个数 + /// 年 + /// 日 + /// 月 + /// 时 + /// 秒 + /// 分 + /// 毫秒 public GetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode, byte writeByteCount, ushort year, byte day, byte month, ushort hour, byte second, byte minute, ushort millisecond) @@ -240,20 +455,37 @@ namespace Modbus.Net.Modbus Time = new DateTime(year, month, day, hour, minute, second, millisecond); } + /// + /// 从站号 + /// public byte SlaveAddress { get; private set; } + /// + /// 功能码 + /// public byte FunctionCode { get; private set; } + /// + /// 写入个数 + /// public byte WriteByteCount { get; private set; } + /// + /// 时间 + /// public DateTime Time { get; private set; } } /// - /// 读系统时间 + /// 读系统时间协议 /// public class GetSystemTimeModbusProtocal : ProtocalUnit { + /// + /// 格式化 + /// + /// 写系统时间参数 + /// 写系统时间的核心 public override byte[] Format(IInputStruct message) { var r_message = (GetSystemTimeModbusInputStruct) message; @@ -261,6 +493,12 @@ namespace Modbus.Net.Modbus r_message.StartAddress, r_message.GetCount); } + /// + /// 反格式化 + /// + /// 获取的信息 + /// 当前反格式化的位置 + /// 反格式化的信息 public override IOutputStruct Unformat(byte[] messageBytes, ref int flag) { var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); @@ -282,8 +520,16 @@ namespace Modbus.Net.Modbus #region 写PLC时间 + /// + /// 写时间输入 + /// public class SetSystemTimeModbusInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 时间 public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time) { SlaveAddress = slaveAddress; @@ -300,33 +546,79 @@ namespace Modbus.Net.Modbus Millisecond = (ushort) time.Millisecond; } + /// + /// 从站号 + /// public byte SlaveAddress { get; } + /// + /// 功能码 + /// public byte FunctionCode { get; } + /// + /// 开始地址 + /// public ushort StartAddress { get; } + /// + /// 写入个数 + /// public ushort WriteCount { get; } + /// + /// 写入字节个数 + /// public byte WriteByteCount { get; } + /// + /// 年 + /// public ushort Year { get; } + /// + /// 日 + /// public byte Day { get; } + /// + /// 月 + /// public byte Month { get; } + /// + /// 时 + /// public ushort Hour { get; } + /// + /// 秒 + /// public byte Second { get; } + /// + /// 分 + /// public byte Minute { get; } + /// + /// 毫秒 + /// public ushort Millisecond { get; } } + /// + /// 写时间输出 + /// public class SetSystemTimeModbusOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 功能码 + /// 开始地址 + /// 写入个数 public SetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode, ushort startAddress, ushort writeCount) { @@ -336,20 +628,37 @@ namespace Modbus.Net.Modbus WriteCount = writeCount; } + /// + /// 从站号 + /// public byte SlaveAddress { get; private set; } + /// + /// 功能码 + /// public byte FunctionCode { get; private set; } + /// + /// 开始地址 + /// public ushort StartAddress { get; private set; } + /// + /// 写入个数 + /// public ushort WriteCount { get; private set; } } /// - /// 写系统时间 + /// 写系统时间协议 /// public class SetSystemTimeModbusProtocal : ProtocalUnit { + /// + /// 格式化 + /// + /// 写系统时间的参数 + /// 写系统时间的核心 public override byte[] Format(IInputStruct message) { var r_message = (SetSystemTimeModbusInputStruct) message; @@ -359,6 +668,12 @@ namespace Modbus.Net.Modbus r_message.Month, r_message.Hour, r_message.Second, r_message.Minute, r_message.Millisecond); } + /// + /// 反格式化 + /// + /// 获取的信息 + /// 当前反格式化的位置 + /// 反格式化的信息 public override IOutputStruct Unformat(byte[] messageBytes, ref int flag) { var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); @@ -388,12 +703,19 @@ namespace Modbus.Net.Modbus {501, "RTU_ILLEGAL_CRC"} }; + /// + /// Modbus错误 + /// + /// Modbus错误号 public ModbusProtocalErrorException(int messageNumber) : base(ProtocalErrorDictionary[messageNumber]) { ErrorMessageNumber = messageNumber; } + /// + /// Modbus错误号 + /// public int ErrorMessageNumber { get; private set; } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs index ae67594..83a9cca 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocalLinkerBytesExtend.cs @@ -10,6 +10,11 @@ namespace Modbus.Net.Modbus /// public class ModbusTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend { + /// + /// 协议扩展,协议内容发送前调用 + /// + /// 扩展前的原始协议内容 + /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { //Modbus/Tcp协议扩张,前面加6个字节,前面4个为0,后面两个为协议整体内容的长度 @@ -22,6 +27,11 @@ namespace Modbus.Net.Modbus return newFormat; } + /// + /// 协议收缩,协议内容接收后调用 + /// + /// 收缩前的完整协议内容 + /// 收缩后的协议内容 public byte[] BytesDecact(byte[] content) { //Modbus/Tcp协议收缩,抛弃前面6个字节的内容 @@ -31,8 +41,16 @@ namespace Modbus.Net.Modbus } } + /// + /// Rtu协议字节伸缩 + /// public class ModbusRtuProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend { + /// + /// 协议扩展,协议内容发送前调用 + /// + /// 扩展前的原始协议内容 + /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { var crc = new byte[2]; @@ -44,6 +62,11 @@ namespace Modbus.Net.Modbus return newFormat; } + /// + /// 协议收缩,协议内容接收后调用 + /// + /// 收缩前的完整协议内容 + /// 收缩后的协议内容 public byte[] BytesDecact(byte[] content) { //Modbus/Rtu协议收缩,抛弃后面2个字节的内容 @@ -53,8 +76,16 @@ namespace Modbus.Net.Modbus } } + /// + /// Ascii协议字节伸缩 + /// public class ModbusAsciiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend { + /// + /// 协议扩展,协议内容发送前调用 + /// + /// 扩展前的原始协议内容 + /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { //Modbus/Ascii协议扩张,前面增加:,后面增加LRC校验和尾字符 @@ -68,6 +99,11 @@ namespace Modbus.Net.Modbus return newContent.ToArray(); } + /// + /// 协议收缩,协议内容接收后调用 + /// + /// 收缩前的完整协议内容 + /// 收缩后的协议内容 public byte[] BytesDecact(byte[] content) { //Modbus/Ascii协议收缩,抛弃头尾。 diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs index aace433..46a7b17 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocal.cs @@ -7,11 +7,24 @@ namespace Modbus.Net.Modbus /// public class ModbusRtuProtocal : ModbusProtocal { + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 + /// 端格式 public ModbusRtuProtocal(byte slaveAddress, byte masterAddress, Endian endian) : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, endian) { } + /// + /// 构造函数 + /// + /// 串口 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusRtuProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs index 6fa4466..7c58088 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocalLinker.cs @@ -7,13 +7,24 @@ namespace Modbus.Net.Modbus /// public class ModbusRtuProtocalLinker : ComProtocalLinker { + /// + /// 构造函数 + /// + /// 串口地址 + /// 从站号 public ModbusRtuProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) { } + /// + /// 校验返回数据 + /// + /// 设备返回的数据 + /// 数据是否正确 public override bool? CheckRight(byte[] content) { + //ProtocalLinker的CheckRight不会返回null if (!base.CheckRight(content).Value) return false; //CRC校验失败 if (!Crc16.GetInstance().CrcEfficacy(content)) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs index a15b339..2822c8f 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocal.cs @@ -7,17 +7,38 @@ namespace Modbus.Net.Modbus /// public class ModbusTcpProtocal : ModbusProtocal { + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 + /// 端格式 public ModbusTcpProtocal(byte slaveAddress, byte masterAddress, Endian endian) : this(ConfigurationManager.AppSettings["IP"], slaveAddress, masterAddress, endian) { } + /// + /// 构造函数 + /// + /// ip地址 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusTcpProtocal(string ip, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { ProtocalLinker = new ModbusTcpProtocalLinker(ip); } + /// + /// 构造函数 + /// + /// ip地址 + /// 端口 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusTcpProtocal(string ip, int port, byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian) { diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs index f0cfe6e..18b4744 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocalLinker.cs @@ -7,17 +7,32 @@ namespace Modbus.Net.Modbus /// public class ModbusTcpProtocalLinker : TcpProtocalLinker { + /// + /// 构造函数 + /// + /// IP地址 public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"] ?? "502")) { } + /// + /// 构造函数 + /// + /// IP地址 + /// 端口 public ModbusTcpProtocalLinker(string ip, int port) : base(ip, port) { } + /// + /// 校验返回数据 + /// + /// 设备返回的数据 + /// 数据是否正确 public override bool? CheckRight(byte[] content) { + //ProtocalLinker的CheckRight不会返回null if (!base.CheckRight(content).Value) return false; //长度校验失败 if (content[5] != content.Length - 6) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index 95a751f..8aba0ad 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Serilog; namespace Modbus.Net.Modbus { @@ -34,6 +35,13 @@ namespace Modbus.Net.Modbus /// private ModbusType _modbusType; + /// + /// 构造函数 + /// + /// 协议类型 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) : base(slaveAddress, masterAddress) @@ -44,6 +52,14 @@ namespace Modbus.Net.Modbus AddressTranslator = new AddressTranslatorModbus(); } + /// + /// 构造函数 + /// + /// 协议类型 + /// 连接地址 + /// 从站号 + /// 主站号 + /// 端格式 public ModbusUtility(ModbusType connectionType, string connectionString, byte slaveAddress, byte masterAddress, Endian endian = Endian.BigEndianLsb) : base(slaveAddress, masterAddress) @@ -54,8 +70,14 @@ namespace Modbus.Net.Modbus AddressTranslator = new AddressTranslatorModbus(); } + /// + /// 端格式 + /// public override Endian Endian { get; } + /// + /// Ip地址 + /// protected string ConnectionStringIp { get @@ -65,6 +87,9 @@ namespace Modbus.Net.Modbus } } + /// + /// 端口 + /// protected int? ConnectionStringPort { get @@ -76,13 +101,17 @@ namespace Modbus.Net.Modbus { return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); } - catch + catch (Exception e) { + Log.Error(e, $"ModbusUtility: {ConnectionString} format error"); return null; } } } + /// + /// 协议类型 + /// public ModbusType ModbusType { get { return _modbusType; } @@ -136,8 +165,9 @@ namespace Modbus.Net.Modbus Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct); return outputStruct?.Time ?? DateTime.MinValue; } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> GetTime: {ConnectionString} error"); return DateTime.MinValue; } } @@ -157,12 +187,17 @@ namespace Modbus.Net.Modbus Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct); return outputStruct?.WriteCount > 0; } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> SetTime: {ConnectionString} error"); return false; } } + /// + /// 设置协议类型 + /// + /// 协议类型 public override void SetConnectionType(int connectionType) { ModbusType = (ModbusType) connectionType; @@ -185,8 +220,9 @@ namespace Modbus.Net.Modbus inputStruct); return outputStruct?.DataValue; } - catch + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -208,8 +244,9 @@ namespace Modbus.Net.Modbus inputStruct); return outputStruct?.WriteCount == setContents.Length; } - catch + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); return false; } } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index 6c10bc7..b4281d5 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -5,6 +5,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Hylasoft.Opc.Common; +using Serilog; namespace Modbus.Net.OPC { @@ -28,12 +29,12 @@ namespace Modbus.Net.OPC Client?.Dispose(); Client = null; _connect = false; - AddInfo("client disconnected successfully."); + Log.Information("opc client {ConnectionToken} disconnected success", ConnectionToken); return true; } catch (Exception ex) { - AddInfo("client disconnected exception: " + ex.Message); + Log.Error(ex, "opc client {ConnectionToken} disconnected error", ConnectionToken); _connect = false; return false; } @@ -125,7 +126,7 @@ namespace Modbus.Net.OPC } catch (Exception e) { - AddInfo("opc write exception:" + e.Message); + Log.Error(e, "opc client {ConnectionToken} write exception", ConnectionToken); return new OpcParamOut { Success = false @@ -144,7 +145,7 @@ namespace Modbus.Net.OPC } catch (Exception e) { - AddInfo("opc client exception:" + e.Message); + Log.Error(e, "opc client {ConnectionToken} read exception", ConnectionToken); return new OpcParamOut { Success = false, @@ -180,13 +181,12 @@ namespace Modbus.Net.OPC { Client.Connect(); _connect = true; - AddInfo("client connected."); + Log.Information("opc client {ConnectionToken} connect success", ConnectionToken); return true; } catch (Exception ex) { - AddInfo("client connected exception: " + ex.Message); - AddInfo("connect failed."); + Log.Error(ex, "opc client {ConnectionToken} connected failed", ConnectionToken); _connect = false; return false; } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index 5b8f454..8da536b 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Serilog; namespace Modbus.Net.OPC { @@ -34,8 +35,9 @@ namespace Modbus.Net.OPC readRequestOpcInputStruct); return readRequestOpcOutputStruct?.GetValue; } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"OpcUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -54,6 +56,7 @@ namespace Modbus.Net.OPC } catch (Exception e) { + Log.Error(e, $"OpcUtility -> SetDatas: {ConnectionString} error"); return false; } } diff --git a/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs b/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs index 923e4c1..e2ba25b 100644 --- a/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs +++ b/Modbus.Net/Modbus.Net.Siemens/AddressFormaterSiemens.cs @@ -5,11 +5,24 @@ /// public class AddressFormaterSiemens : AddressFormater { + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 编码后的地址 public override string FormatAddress(string area, int address) { return area + " " + address; } + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 子地址 + /// 编码后的地址 public override string FormatAddress(string area, int address, int subAddress) { return area + " " + address + "." + subAddress; @@ -21,6 +34,12 @@ /// public class AddressFormaterSimenseStandard : AddressFormater { + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 编码后的地址 public override string FormatAddress(string area, int address) { if (area.Length > 1 && @@ -29,6 +48,13 @@ return area.ToUpper() + address; } + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 子地址 + /// 编码后的地址 public override string FormatAddress(string area, int address, int subAddress) { if (area.Length > 1 && diff --git a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs index b19dbb2..fd69247 100644 --- a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs +++ b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs @@ -9,8 +9,14 @@ namespace Modbus.Net.Siemens /// public class AddressTranslatorSiemens : AddressTranslator { + /// + /// 区域的翻译字典 + /// protected Dictionary AreaCodeDictionary; + /// + /// 构造函数 + /// public AddressTranslatorSiemens() { AreaCodeDictionary = new Dictionary @@ -30,6 +36,12 @@ namespace Modbus.Net.Siemens }; } + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 翻译后的地址 public override AddressDef AddressTranslate(string address, bool isRead) { address = address.ToUpper(); @@ -68,6 +80,11 @@ namespace Modbus.Net.Siemens }; } + /// + /// 获取区域中的单个地址占用的字节长度 + /// + /// 区域名称 + /// 字节长度 public override double GetAreaByteLength(string area) { return 1; @@ -79,8 +96,14 @@ namespace Modbus.Net.Siemens /// public class AddressTranslatorSimenseStandard : AddressTranslator { + /// + /// 区域的翻译字典 + /// protected Dictionary AreaCodeDictionary; + /// + /// 构造函数 + /// public AddressTranslatorSimenseStandard() { AreaCodeDictionary = new Dictionary @@ -100,6 +123,12 @@ namespace Modbus.Net.Siemens }; } + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 翻译后的地址 public override AddressDef AddressTranslate(string address, bool isRead) { address = address.ToUpper(); @@ -134,6 +163,11 @@ namespace Modbus.Net.Siemens }; } + /// + /// 获取区域中的单个地址占用的字节长度 + /// + /// 区域名称 + /// 字节长度 public override double GetAreaByteLength(string area) { return 1; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs index f91495c..3a5fb32 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs @@ -9,6 +9,16 @@ namespace Modbus.Net.Siemens public class SiemensMachine : BaseMachine where TKey : IEquatable where TUnitKey : IEquatable { + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 设备类型 + /// 读写的地址 + /// 是否保持连接 + /// 从站号 + /// 主站号 public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, IEnumerable> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress) : base(getAddresses, keepConnect, slaveAddress, masterAddress) @@ -19,6 +29,15 @@ namespace Modbus.Net.Siemens AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 设备类型 + /// 读写的地址 + /// 从站号 + /// 主站号 public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, IEnumerable> getAddresses, byte slaveAddress, byte masterAddress) : this(connectionType, connectionString, model, getAddresses, false, slaveAddress, masterAddress) @@ -31,6 +50,16 @@ namespace Modbus.Net.Siemens /// public class SiemensMachine : BaseMachine { + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 设备类型 + /// 读写的地址 + /// 是否保持连接 + /// 从站号 + /// 主站号 public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, IEnumerable getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress) : base(getAddresses, keepConnect, slaveAddress, masterAddress) @@ -41,6 +70,15 @@ namespace Modbus.Net.Siemens AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接地址 + /// 设备类型 + /// 读写的地址 + /// 从站号 + /// 主站号 public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, IEnumerable getAddresses, byte slaveAddress, byte masterAddress) : this(connectionType, connectionString, model, getAddresses, false, slaveAddress, masterAddress) diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs index a14fc97..269bcd0 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs @@ -10,22 +10,43 @@ namespace Modbus.Net.Siemens { private readonly string _com; + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 public SiemensPpiProtocal(byte slaveAddress, byte masterAddress) : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress) { } + /// + /// 构造函数 + /// + /// 串口地址 + /// 从站号 + /// 主站号 public SiemensPpiProtocal(string com, byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress) { _com = com; } + /// + /// 发送协议内容并接收,一般方法 + /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 public override byte[] SendReceive(params object[] content) { return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content)); } + /// + /// 发送协议内容并接收,一般方法 + /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 public override async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) @@ -33,16 +54,30 @@ namespace Modbus.Net.Siemens return await base.SendReceiveAsync(Endian, content); } + /// + /// 强行发送,不检测连接状态 + /// + /// 协议核心 + /// 协议的参数 + /// 设备返回的信息 private async Task ForceSendReceiveAsync(ProtocalUnit unit, IInputStruct content) { return await base.SendReceiveAsync(unit, content); } + /// + /// 连接设备 + /// + /// 是否连接成功 public override bool Connect() { - return AsyncHelper.RunSync(() => ConnectAsync()); + return AsyncHelper.RunSync(ConnectAsync); } + /// + /// 连接设备 + /// + /// 是否连接成功 public override async Task ConnectAsync() { ProtocalLinker = new SiemensPpiProtocalLinker(_com, SlaveAddress); diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs index 6c8c0e0..01a6ef2 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs @@ -9,11 +9,21 @@ namespace Modbus.Net.Siemens /// public class SiemensPpiProtocalLinker : ComProtocalLinker { + /// + /// 构造函数 + /// + /// 串口地址 + /// 从站号 public SiemensPpiProtocalLinker(string com, int slaveAddress) : base(com, 9600, Parity.Even, StopBits.One, 8, slaveAddress) { } + /// + /// 发送协议内容并接收返回 + /// + /// 发送的报文 + /// 接收的报文 public override async Task SendReceiveAsync(byte[] content) { var extBytes = BytesExtend(content); @@ -36,6 +46,11 @@ namespace Modbus.Net.Siemens return BytesDecact(receiveBytes); } + /// + /// 发送协议内容并接收返回,不进行协议扩展和收缩 + /// + /// 发送的报文 + /// 接收的报文 public override async Task SendReceiveWithoutExtAndDecAsync(byte[] content) { var ans = await base.SendReceiveWithoutExtAndDecAsync(content); @@ -60,6 +75,11 @@ namespace Modbus.Net.Siemens return ans; } + /// + /// 校验报文 + /// + /// 设备返回的信息 + /// 报文是否正确 public override bool? CheckRight(byte[] content) { if (!base.CheckRight(content).Value) return false; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs index 64af6bd..d5ae066 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocalLinkerBytesExtend.cs @@ -7,6 +7,11 @@ namespace Modbus.Net.Siemens /// public class SiemensTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend { + /// + /// 协议扩展,协议内容发送前调用 + /// + /// 扩展前的原始协议内容 + /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { Array.Copy(new byte[] {0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80}, 0, content, 0, 7); @@ -14,6 +19,11 @@ namespace Modbus.Net.Siemens return content; } + /// + /// 协议收缩,协议内容接收后调用 + /// + /// 收缩前的完整协议内容 + /// 收缩后的协议内容 public byte[] BytesDecact(byte[] content) { var newContent = new byte[content.Length - 7]; @@ -27,6 +37,11 @@ namespace Modbus.Net.Siemens /// public class SiemensPpiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend { + /// + /// 协议扩展,协议内容发送前调用 + /// + /// 扩展前的原始协议内容 + /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { var newContent = new byte[content.Length + 2]; @@ -42,6 +57,11 @@ namespace Modbus.Net.Siemens return newContent; } + /// + /// 协议收缩,协议内容接收后调用 + /// + /// 收缩前的完整协议内容 + /// 收缩后的协议内容 public byte[] BytesDecact(byte[] content) { var newContent = new byte[content.Length - 9]; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs index fc1d577..c5d8c09 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocal.cs @@ -18,12 +18,31 @@ namespace Modbus.Net.Siemens private readonly ushort _tsapDst; 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.AppSettings["IP"]) { } + /// + /// 构造函数 + /// + /// + /// + /// + /// + /// + /// + /// IP地址 public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, ushort maxPdu, string ip) : this( @@ -32,6 +51,17 @@ namespace Modbus.Net.Siemens { } + /// + /// 构造函数 + /// + /// + /// + /// + /// + /// + /// + /// IP地址 + /// 端口 public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, ushort maxPdu, string ip, int port) : base(0, 0) { @@ -46,11 +76,21 @@ namespace Modbus.Net.Siemens _connectTryCount = 0; } + /// + /// 发送数据并接收 + /// + /// 发送的数据 + /// 返回的数据 public override byte[] SendReceive(params object[] content) { return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content)); } + /// + /// 发送数据并接收 + /// + /// 发送的数据 + /// 返回的数据 public override async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) @@ -58,11 +98,23 @@ namespace Modbus.Net.Siemens return await base.SendReceiveAsync(Endian, content); } + /// + /// 发送数据并接收 + /// + /// 协议的核心 + /// 协议的参数 + /// 返回的数据 public override IOutputStruct SendReceive(ProtocalUnit unit, IInputStruct content) { return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); } + /// + /// 发送数据并接收 + /// + /// 发送的数据 + /// 协议的参数 + /// 返回的数据 public override async Task SendReceiveAsync(ProtocalUnit unit, IInputStruct content) { if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content); @@ -74,16 +126,30 @@ namespace Modbus.Net.Siemens .ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null); } + /// + /// 强制发送数据并接收 + /// + /// 发送的数据 + /// 协议的参数 + /// 返回的数据 private async Task ForceSendReceiveAsync(ProtocalUnit unit, IInputStruct content) { return await base.SendReceiveAsync(unit, content); } + /// + /// 连接设备 + /// + /// 设备是否连接成功 public override bool Connect() { return AsyncHelper.RunSync(ConnectAsync); } + /// + /// 连接设备 + /// + /// 设备是否连接成功 public override async Task ConnectAsync() { _connectTryCount++; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs index ffbeabf..14be570 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocalLinker.cs @@ -8,16 +8,30 @@ namespace Modbus.Net.Siemens /// public class SiemensTcpProtocalLinker : TcpProtocalLinker { + /// + /// 构造函数 + /// + /// IP地址 public SiemensTcpProtocalLinker(string ip) : this(ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"] ?? "102")) { } + /// + /// 构造函数 + /// + /// IP地址 + /// 端口 public SiemensTcpProtocalLinker(string ip, int port) : base(ip, port) { } + /// + /// 校验报文 + /// + /// 设备返回的信息 + /// 报文是否正确 public override bool? CheckRight(byte[] content) { if (!base.CheckRight(content).Value) return false; diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs index 4d81d49..aeeb360 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs @@ -1,22 +1,56 @@ using System; using System.Threading.Tasks; +using Serilog; namespace Modbus.Net.Siemens { + /// + /// 西门子协议类型 + /// public enum SiemensType { + /// + /// PPI + /// Ppi = 0, + /// + /// MPI + /// Mpi = 1, + /// + /// 以太网 + /// Tcp = 2 } + /// + /// 西门子设备类型 + /// public enum SiemensMachineModel { + /// + /// S7-200 + /// S7_200 = 0, + /// + /// S7-200 Smart + /// S7_200_Smart = 1, + /// + /// S7-300 + /// S7_300 = 2, + /// + /// S7-400 + /// S7_400 = 3, + /// + /// S7-1200 + /// S7_1200 = 4, + /// + /// S7-1500 + /// S7_1500 = 5 } @@ -34,6 +68,14 @@ namespace Modbus.Net.Siemens private SiemensType _siemensType; + /// + /// 构造函数 + /// + /// 连接类型 + /// 连接字符串 + /// 设备类型 + /// 从站地址 + /// 主站地址 public SiemensUtility(SiemensType connectionType, string connectionString, SiemensMachineModel model, byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress) { @@ -84,15 +126,21 @@ namespace Modbus.Net.Siemens } default: { - throw new NotImplementedException("没有相应的西门子类型"); + throw new NotImplementedException("Siemens PLC Model not Supported"); } } ConnectionType = connectionType; AddressTranslator = new AddressTranslatorSiemens(); } + /// + /// 端格式 + /// public override Endian Endian => Endian.BigEndianLsb; + /// + /// IP地址 + /// protected string ConnectionStringIp { get @@ -102,6 +150,9 @@ namespace Modbus.Net.Siemens } } + /// + /// 端口 + /// protected int? ConnectionStringPort { get @@ -113,8 +164,9 @@ namespace Modbus.Net.Siemens { return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); } - catch + catch (Exception e) { + Log.Error(e, $"SiemensUtility: {ConnectionString} format error"); return null; } } @@ -188,8 +240,9 @@ namespace Modbus.Net.Siemens readRequestSiemensInputStruct); return readRequestSiemensOutputStruct?.GetValue; } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"SiemensUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -213,8 +266,9 @@ namespace Modbus.Net.Siemens writeRequestSiemensInputStruct); return writeRequestSiemensOutputStruct?.AccessResult == SiemensAccessResult.NoError; } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error"); return false; } } diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs index 3454532..71ab2d2 100644 --- a/Modbus.Net/Modbus.Net/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/ComConnector.cs @@ -61,15 +61,16 @@ namespace Modbus.Net /// private readonly int _timeoutTime; + private int _errorCount; + private int _receiveCount; + + private int _sendCount; + /// /// Dispose是否执行 /// private bool m_disposed; - private int _sendCount; - private int _receiveCount; - private int _errorCount; - /// /// 构造器 /// @@ -144,7 +145,7 @@ namespace Modbus.Net /// 字节间隔最大时间 /// 串口实际读入数据个数 public int ReadComm(out byte[] readBuf, int bufRoom, int howTime, int byteTime) - { + { readBuf = new byte[1023]; Array.Clear(readBuf, 0, readBuf.Length); @@ -283,7 +284,7 @@ namespace Modbus.Net { SerialPort.Close(); } - catch (Exception) + catch { //ignore } @@ -308,6 +309,24 @@ namespace Modbus.Net Dispose(false); } + private void RefreshSendCount() + { + _sendCount++; + Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); + } + + private void RefreshReceiveCount() + { + _receiveCount++; + Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + } + + private void RefreshErrorCount() + { + _errorCount++; + Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + } + #region 发送接收数据 /// @@ -381,7 +400,8 @@ namespace Modbus.Net Log.Error(e, "Com client {ConnectionToken} disconnect error", ConnectionToken); return false; } - Log.Error(new Exception("Linkers or Connectors Dictionary not found"), "Com client {ConnectionToken} disconnect error", ConnectionToken); + Log.Error(new Exception("Linkers or Connectors Dictionary not found"), + "Com client {ConnectionToken} disconnect error", ConnectionToken); return false; } @@ -436,7 +456,8 @@ namespace Modbus.Net { try { - Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); + Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, + sendbytes.Length); Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); SerialPort.Write(sendbytes, 0, sendbytes.Length); } @@ -450,8 +471,10 @@ namespace Modbus.Net try { returnBytes = ReadMsg(); - Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, returnBytes.Length); - Log.Verbose("Com client {ConnectionToken} receive msg: {SendBytes}", ConnectionToken, returnBytes); + Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, + returnBytes.Length); + Log.Verbose("Com client {ConnectionToken} receive msg: {SendBytes}", ConnectionToken, + returnBytes); } catch (Exception e) { @@ -504,7 +527,8 @@ namespace Modbus.Net { try { - Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); + Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, + sendbytes.Length); Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); SerialPort.Write(sendbytes, 0, sendbytes.Length); } @@ -513,7 +537,7 @@ namespace Modbus.Net Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken); Dispose(); return false; - } + } RefreshSendCount(); } return true; @@ -549,23 +573,5 @@ namespace Modbus.Net } #endregion - - private void RefreshSendCount() - { - _sendCount++; - Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); - } - - private void RefreshReceiveCount() - { - _receiveCount++; - Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); - } - - private void RefreshErrorCount() - { - _errorCount++; - Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); - } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/AddressTranslator.cs b/Modbus.Net/src/Base.Common/AddressTranslator.cs index 98553a3..f5f07eb 100644 --- a/Modbus.Net/src/Base.Common/AddressTranslator.cs +++ b/Modbus.Net/src/Base.Common/AddressTranslator.cs @@ -52,9 +52,9 @@ namespace Modbus.Net /// /// 地址转换 /// - /// 地址前地址 + /// 格式化的地址 /// 是否为读取,是为读取,否为写入 - /// Key为转换后的地址,Value为辅助码 + /// 翻译后的地址 public abstract AddressDef AddressTranslate(string address, bool isRead); /// diff --git a/Modbus.Net/src/Base.Common/BaseConnector.cs b/Modbus.Net/src/Base.Common/BaseConnector.cs index 0d32421..1232ac8 100644 --- a/Modbus.Net/src/Base.Common/BaseConnector.cs +++ b/Modbus.Net/src/Base.Common/BaseConnector.cs @@ -7,7 +7,6 @@ namespace Modbus.Net /// public abstract class BaseConnector : BaseConnector { - } /// diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 3cfabb5..8331af7 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Serilog; namespace Modbus.Net { @@ -333,8 +334,9 @@ namespace Modbus.Net } catch (Exception e) { - Console.WriteLine(ConnectionToken + " " + e.Message); ErrorCount++; + Log.Error(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); + if (ErrorCount >= _maxErrorCount) Disconnect(); return null; @@ -532,7 +534,11 @@ namespace Modbus.Net } catch (Exception e) { - Console.WriteLine(ConnectionToken + " " + e.Message); + ErrorCount++; + Log.Error(e, $"BaseMachine -> SetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); + + if (ErrorCount >= _maxErrorCount) + Disconnect(); return false; } return true; @@ -591,7 +597,7 @@ namespace Modbus.Net .Invoke(this, parameters); return (TReturnType) returnValue; } - throw new InvalidCastException($"Machine未实现{typeof(TMachineMethod).Name}的接口"); + throw new InvalidCastException($"Machine interface {nameof(TMachineMethod)} not implemented"); } /// @@ -641,9 +647,9 @@ namespace Modbus.Net { return GetAddresses.SingleOrDefault(p => p.Id.Equals(addressUnitId)); } - catch (Exception) + catch (Exception e) { - Console.WriteLine("Id重复,请检查"); + Log.Error(e, $"BaseMachine -> GetAddressUnitById Id:{Id} ConnectionToken:{ConnectionToken} addressUnitId:{addressUnitId} Repeated"); return null; } } diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 5b7b5f7..2d90475 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -85,7 +85,8 @@ namespace Modbus.Net //自动寻找存在的协议并将其加载 var protocalUnit = Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; - if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容"); + if (protocalUnit == null) + throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented"); protocalUnit.Endian = Endian; Register(protocalUnit); return Protocals[protocalName]; diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index 09a4dde..ddb7331 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Serilog; /// /// 端格式 @@ -124,8 +125,9 @@ namespace Modbus.Net var getBytes = getReturnValue; return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount); } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error"); return null; } } @@ -159,8 +161,9 @@ namespace Modbus.Net new KeyValuePair(typeof(T), getByteCount)); return ValueHelper.GetInstance(Endian).ObjectArrayToDestinationArray(getBytes); } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> GetDatas Generic: {ConnectionString} error"); return null; } } @@ -199,8 +202,9 @@ namespace Modbus.Net var getBytes = getReturnValue; return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount); } - catch (Exception) + catch (Exception e) { + Log.Error(e, $"ModbusUtility -> GetDatas pair: {ConnectionString} error"); return null; } } @@ -290,7 +294,7 @@ namespace Modbus.Net .Invoke(this, parameters); return (TReturnType) returnValue; } - throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口"); + throw new InvalidCastException($"Utility interface {nameof(TUtilityMethod)} not implemented"); } /// diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 3169381..22305db 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Nito.AsyncEx; +using Serilog; namespace Modbus.Net { @@ -864,7 +865,7 @@ namespace Modbus.Net } catch (Exception e) { - Console.WriteLine($"设备返回错误 {e.Message}"); + Log.Error(e, $"Device {id} return error"); return null; } } @@ -889,7 +890,7 @@ namespace Modbus.Net } catch (Exception e) { - Console.WriteLine($"设备返回错误 {e.Message}"); + Log.Error(e, $"Device {connectionToken} return error"); return null; } } diff --git a/Modbus.Net/src/Base.Common/TcpConnector.cs b/Modbus.Net/src/Base.Common/TcpConnector.cs index 8f1a56e..2e71893 100644 --- a/Modbus.Net/src/Base.Common/TcpConnector.cs +++ b/Modbus.Net/src/Base.Common/TcpConnector.cs @@ -40,9 +40,10 @@ namespace Modbus.Net /// private readonly byte[] _receiveBuffer = new byte[1024]; - private int _sendCount; - private int _receiveCount; private int _errorCount; + private int _receiveCount; + + private int _sendCount; private TcpClient _socketClient; @@ -73,7 +74,8 @@ namespace Modbus.Net /// public int TimeoutTime { - get => _timeoutTime; + get => + _timeoutTime; set { _timeoutTime = value; @@ -122,7 +124,7 @@ namespace Modbus.Net #endif Log.Debug("Tcp client {ConnectionToken} Disposed", ConnectionToken); } - m_disposed = true; + m_disposed = true; } } @@ -242,7 +244,7 @@ namespace Modbus.Net await stream.WriteAsync(datagram, 0, datagram.Length); RefreshSendCount(); - + return true; } catch (Exception err) @@ -282,11 +284,12 @@ namespace Modbus.Net Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); Log.Verbose("Tcp client {ConnectionToken} send: {Datagram}", ConnectionToken, datagram); await stream.WriteAsync(datagram, 0, datagram.Length); - + RefreshSendCount(); var receiveBytes = await ReceiveAsync(stream); - Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, receiveBytes.Length); + Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, + receiveBytes.Length); Log.Verbose("Tcp client {ConnectionToken} receive: {Datagram}", ConnectionToken, receiveBytes); return receiveBytes; @@ -332,7 +335,7 @@ namespace Modbus.Net var replyMessage = new byte[len]; Array.Copy(_receiveBuffer, replyMessage, len); - Log.Verbose("Tcp client {ConnectionToken} reply: {replyMessage}",ConnectionToken, replyMessage); + Log.Verbose("Tcp client {ConnectionToken} reply: {replyMessage}", ConnectionToken, replyMessage); RefreshReceiveCount(); if (len <= 0) diff --git a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs index 6a86707..17b7c91 100644 --- a/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/TcpProtocalLinker.cs @@ -1,6 +1,6 @@ - -#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47 +#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47 using System.Configuration; + #endif namespace Modbus.Net diff --git a/Modbus.Net/src/Base.Common/TypeExtensions.cs b/Modbus.Net/src/Base.Common/TypeExtensions.cs index b81436f..25a197e 100644 --- a/Modbus.Net/src/Base.Common/TypeExtensions.cs +++ b/Modbus.Net/src/Base.Common/TypeExtensions.cs @@ -36,7 +36,7 @@ namespace Modbus.Net throw new NullReferenceException("The type has not been specified."); if (string.IsNullOrEmpty(methodName)) - throw new ArgumentNullException("methodName", "The name of the method has not been specified."); + throw new ArgumentNullException(nameof(methodName), "The name of the method has not been specified."); var methods = diff --git a/Modbus.Net/src/Base.Common/ValueHelper.cs b/Modbus.Net/src/Base.Common/ValueHelper.cs index 01a2897..7d0a1cf 100644 --- a/Modbus.Net/src/Base.Common/ValueHelper.cs +++ b/Modbus.Net/src/Base.Common/ValueHelper.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; +using Serilog; namespace Modbus.Net { @@ -707,12 +708,13 @@ namespace Modbus.Net } default: { - throw new NotImplementedException("没有实现除整数以外的其它转换方式"); + throw new NotImplementedException("Number casting not implemented"); } } } - catch (Exception) + catch (Exception e) { + Log.Error(e, "ValueHelper -> ByteArrayToObjectArray error"); count = contents.Length; } } @@ -798,7 +800,7 @@ namespace Modbus.Net } default: { - throw new NotImplementedException("没有实现除整数以外的其它转换方式"); + throw new NotImplementedException("Number casting not implemented"); } } } @@ -818,8 +820,9 @@ namespace Modbus.Net Array.Copy(datas, 0, contents, pos, datas.Length); return true; } - catch (Exception) + catch (Exception e) { + Log.Error(e, "ValueHelper -> SetValue set value failed"); return false; } } @@ -866,8 +869,9 @@ namespace Modbus.Net contents[pos] = SetBit(contents[pos], subPos, setValue); return true; } - catch (Exception) + catch (Exception e) { + Log.Error(e, "ValueHelper -> SetBit set bit failed"); return false; } } From 7ab457bf9a5960241b1fa18dfa1b0b11a555ba65 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 17 May 2017 19:05:19 +0800 Subject: [PATCH 17/62] Add Comments --- .../Modbus.Net.Siemens/SiemensProtocal.cs | 250 ++++++++++++++++-- 1 file changed, 233 insertions(+), 17 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs index 588e15c..5a08905 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs @@ -102,8 +102,16 @@ namespace Modbus.Net.Siemens OtherAccess = 0x04 } + /// + /// 西门子协议 + /// public abstract class SiemensProtocal : BaseProtocal { + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 protected SiemensProtocal(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress, Endian.BigEndianLsb) { @@ -187,9 +195,9 @@ namespace Modbus.Net.Siemens TsapDst = dstTsap; } - public byte TdpuSize { get; private set; } - public ushort TsapSrc { get; private set; } - public ushort TsapDst { get; private set; } + public byte TdpuSize { get; } + public ushort TsapSrc { get; } + public ushort TsapDst { get; } } internal class CreateReferenceSiemensProtocal : ProtocalUnit, ISpecialProtocalUnit @@ -248,30 +256,63 @@ namespace Modbus.Net.Siemens #region 串口消息确认 + /// + /// 串口消息确认输入 + /// public class ComConfirmMessageSiemensInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 public ComConfirmMessageSiemensInputStruct(byte slaveAddress, byte masterAddress) { SlaveAddress = slaveAddress; MasterAddress = masterAddress; } + /// + /// 从站号 + /// public byte SlaveAddress { get; set; } + + /// + /// 主站号 + /// public byte MasterAddress { get; set; } } + /// + /// 串口消息确认输出 + /// public class ComConfirmMessageSiemensOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 确认字节 public ComConfirmMessageSiemensOutputStruct(byte confirmByte) { ConfirmByte = confirmByte; } + /// + /// 确认字节 + /// public byte ConfirmByte { get; set; } } + /// + /// 串口消息确认协议 + /// public class ComConfirmMessageSiemensProtocal : ProtocalUnit, ISpecialProtocalUnit { + /// + /// 格式化 + /// + /// 输入参数 + /// 格式化数据 public override byte[] Format(IInputStruct message) { var r_message = (ComConfirmMessageSiemensInputStruct) message; @@ -280,6 +321,12 @@ namespace Modbus.Net.Siemens (byte) 0x16); } + /// + /// 反格式化 + /// + /// 设备返回的数据 + /// 当前反格式化的位置 + /// 输出数据 public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) { var confirmByte = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); @@ -309,7 +356,8 @@ namespace Modbus.Net.Siemens internal class EstablishAssociationSiemensOutputStruct : IOutputStruct { - public EstablishAssociationSiemensOutputStruct(ushort pduRef, ushort maxCalling, ushort maxCalled, ushort maxPdu) + public EstablishAssociationSiemensOutputStruct(ushort pduRef, ushort maxCalling, ushort maxCalled, + ushort maxPdu) { PduRef = pduRef; MaxCalling = maxCalling; @@ -317,10 +365,10 @@ namespace Modbus.Net.Siemens MaxPdu = maxPdu; } - public ushort PduRef { get; private set; } - public ushort MaxCalling { get; private set; } - public ushort MaxCalled { get; private set; } - public ushort MaxPdu { get; private set; } + public ushort PduRef { get; } + public ushort MaxCalling { get; } + public ushort MaxCalled { get; } + public ushort MaxPdu { get; } } internal class EstablishAssociationSiemensProtocal : ProtocalUnit @@ -359,8 +407,21 @@ namespace Modbus.Net.Siemens #region 读数据请求 + /// + /// 读数据输入 + /// public class ReadRequestSiemensInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站号 + /// 主站号 + /// 报文索引 + /// 获取数据类型 + /// 开始地址 + /// 获取个数 + /// 地址转换器 public ReadRequestSiemensInputStruct(byte slaveAddress, byte masterAddress, ushort pduRef, SiemensTypeCode getType, string startAddress, ushort getCount, AddressTranslator addressTranslator) { @@ -376,18 +437,60 @@ namespace Modbus.Net.Siemens NumberOfElements = getCount; } + /// + /// 从站号 + /// public byte SlaveAddress { get; set; } + + /// + /// 主站号 + /// public byte MasterAddress { get; set; } + + /// + /// 报文索引 + /// public ushort PduRef { get; } + + /// + /// 地址类型 + /// public byte TypeCode { get; } + + /// + /// 读取的个数 + /// public ushort NumberOfElements { get; } + + /// + /// DB块 + /// public ushort DbBlock { get; } + + /// + /// 区域 + /// public byte Area { get; } + + /// + /// 起始偏移量 + /// public int Offset { get; } } + /// + /// 读数据输出 + /// public class ReadRequestSiemensOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 报文索引 + /// 访问结果 + /// 数据类型 + /// 获取个数 + /// 读取值 public ReadRequestSiemensOutputStruct(ushort pduRef, SiemensAccessResult accessResult, SiemensDataType dataType, ushort getLength, byte[] value) { @@ -398,15 +501,42 @@ namespace Modbus.Net.Siemens GetValue = value; } - public ushort PduRef { get; private set; } - public SiemensAccessResult AccessResult { get; private set; } - public SiemensDataType DataType { get; private set; } - public ushort GetLength { get; private set; } - public byte[] GetValue { get; private set; } + /// + /// 报文索引 + /// + public ushort PduRef { get; } + + /// + /// 访问结果 + /// + public SiemensAccessResult AccessResult { get; } + + /// + /// 数据类型 + /// + public SiemensDataType DataType { get; } + + /// + /// 获取个数 + /// + public ushort GetLength { get; } + + /// + /// 读取值 + /// + public byte[] GetValue { get; } } + /// + /// 读数据协议 + /// public class ReadRequestSiemensProtocal : ProtocalUnit { + /// + /// 格式化 + /// + /// 输入参数 + /// 格式化数据 public override byte[] Format(IInputStruct message) { var r_message = (ReadRequestSiemensInputStruct) message; @@ -435,6 +565,12 @@ namespace Modbus.Net.Siemens offsetBitBytes.Skip(1).ToArray()); } + /// + /// 反格式化 + /// + /// 设备返回的数据 + /// 当前反格式化的位置 + /// 输出数据 public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) { pos = 4; @@ -455,8 +591,20 @@ namespace Modbus.Net.Siemens #region 写数据请求 + /// + /// 写数据输入 + /// public class WriteRequestSiemensInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 从站地址 + /// 主站地址 + /// 报文索引 + /// 开始地址 + /// 写入值 + /// 地址转换器 public WriteRequestSiemensInputStruct(byte slaveAddress, byte masterAddress, ushort pduRef, string startAddress, object[] writeValue, AddressTranslator addressTranslator) { @@ -471,29 +619,79 @@ namespace Modbus.Net.Siemens WriteValue = writeValue; } + /// + /// 从站地址 + /// public byte SlaveAddress { get; set; } + + /// + /// 主站地址 + /// public byte MasterAddress { get; set; } + + /// + /// 报文索引 + /// public ushort PduRef { get; } + + /// + /// DB块 + /// public ushort DbBlock { get; } + + /// + /// 区域 + /// public byte Area { get; } + + /// + /// 写入偏移量 + /// public int Offset { get; } + + /// + /// 写入值 + /// public object[] WriteValue { get; } } + /// + /// 写数据输出 + /// public class WriteRequestSiemensOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 报文索引 + /// 访问结果 public WriteRequestSiemensOutputStruct(ushort pduRef, SiemensAccessResult accessResult) { PduRef = pduRef; AccessResult = accessResult; } - public ushort PduRef { get; private set; } - public SiemensAccessResult AccessResult { get; private set; } + /// + /// 报文索引 + /// + public ushort PduRef { get; } + + /// + /// 访问结果 + /// + public SiemensAccessResult AccessResult { get; } } + /// + /// 写数据协议 + /// public class WriteRequestSiemensProtocal : ProtocalUnit { + /// + /// 格式化 + /// + /// 输入参数 + /// 格式化数据 public override byte[] Format(IInputStruct message) { var r_message = (WriteRequestSiemensInputStruct) message; @@ -526,6 +724,12 @@ namespace Modbus.Net.Siemens offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes); } + /// + /// 反格式化 + /// + /// 设备返回的数据 + /// 当前反格式化的位置 + /// 输出数据 public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) { if (messageBytes.Length == 1) @@ -653,6 +857,11 @@ namespace Modbus.Net.Siemens {0xEF, "Layer 2 specific error"} }; + /// + /// 构造函数 + /// + /// 错误分类 + /// 错误码 public SiemensProtocalErrorException(int errCls, int errCod) : base(ProtocalErrorDictionary[errCls] + " : " + errCod) { @@ -660,7 +869,14 @@ namespace Modbus.Net.Siemens ErrorCode = errCod; } - public int ErrorClass { get; private set; } - public int ErrorCode { get; private set; } + /// + /// 错误分类 + /// + public int ErrorClass { get; } + + /// + /// 错误码 + /// + public int ErrorCode { get; } } } \ No newline at end of file From 7dd7d0501cd12d6869dabf08593ad2078f4c5989 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 18 May 2017 14:49:13 +0800 Subject: [PATCH 18/62] Add Comments --- .../Modbus.Net.OPC/AddressFormaterOpc.cs | 23 +++++ .../Modbus.Net.OPC/AddressTranslatorOpc.cs | 11 +++ Modbus.Net/Modbus.Net.OPC/ClientExtend.cs | 86 +++++++++++++++++++ .../Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs | 22 +++++ Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 79 +++++++++++++++-- Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs | 14 ++- Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs | 30 +++++++ Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs | 20 +++-- .../Modbus.Net.OPC/OpcDaProtocalLinker.cs | 7 ++ Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs | 4 + Modbus.Net/Modbus.Net.OPC/OpcMachine.cs | 14 ++- Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs | 86 +++++++++++++++++++ Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs | 14 ++- Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs | 30 +++++++ Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs | 17 +++- .../Modbus.Net.OPC/OpcUaProtocalLinker.cs | 9 +- Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs | 6 +- Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 35 +++++++- 18 files changed, 486 insertions(+), 21 deletions(-) diff --git a/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs b/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs index 2d9a4f6..afaf426 100644 --- a/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs +++ b/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs @@ -24,12 +24,28 @@ namespace Modbus.Net.OPC Seperator = seperator; } + /// + /// 设备 + /// public BaseMachine Machine { get; set; } + /// + /// 标签构造器 + /// (设备,地址)->不具备分隔符的标签数组 + /// protected Func, AddressUnit, string[]> TagGeter { get; set; } + /// + /// 分割符 + /// public char Seperator { get; protected set; } + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 编码后的地址 public override string FormatAddress(string area, int address) { var findAddress = Machine?.GetAddresses.FirstOrDefault(p => p.Area == area && p.Address == address); @@ -42,6 +58,13 @@ namespace Modbus.Net.OPC return ans; } + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 子地址(忽略) + /// 编码后的地址 public override string FormatAddress(string area, int address, int subAddress) { return FormatAddress(area, address); diff --git a/Modbus.Net/Modbus.Net.OPC/AddressTranslatorOpc.cs b/Modbus.Net/Modbus.Net.OPC/AddressTranslatorOpc.cs index 71f0d20..892b5c7 100644 --- a/Modbus.Net/Modbus.Net.OPC/AddressTranslatorOpc.cs +++ b/Modbus.Net/Modbus.Net.OPC/AddressTranslatorOpc.cs @@ -7,11 +7,22 @@ namespace Modbus.Net.OPC /// public class AddressTranslatorOpc : AddressTranslator { + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 翻译后的地址 public override AddressDef AddressTranslate(string address, bool isRead) { throw new NotImplementedException(); } + /// + /// 获取区域中的单个地址占用的字节长度 + /// + /// 区域名称 + /// 字节长度 public override double GetAreaByteLength(string area) { return 1; diff --git a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs index d745f7a..43b4e35 100644 --- a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs +++ b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs @@ -7,54 +7,140 @@ using Hylasoft.Opc.Ua; namespace Modbus.Net.OPC { + /// + /// Opc Client Extend interface, Unified for DA and UA + /// public interface IClientExtend : IDisposable { + /// + /// Unified Root Node + /// Node RootNodeBase { get; } + /// + /// Connect the client to the OPC Server + /// void Connect(); + /// + /// Read a tag + /// + /// The type of tag to read + /// + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` reads the tag `bar` on the folder `foo` + /// + /// The value retrieved from the OPC T Read(string tag); + /// + /// Write a value on the specified opc tag + /// + /// The type of tag to write on + /// + /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. + /// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` + /// + /// void Write(string tag, T item); + /// + /// Read a tag asynchronusly + /// Task ReadAsync(string tag); + /// + /// Write a value on the specified opc tag asynchronously + /// Task WriteAsync(string tag, T item); + /// + /// Finds a node on the Opc Server asynchronously + /// Task FindNodeAsync(string tag); + /// + /// Explore a folder on the Opc Server asynchronously + /// Task> ExploreFolderAsync(string tag); } + /// + /// UaClient Extend + /// public class MyDaClient : DaClient, IClientExtend { + /// + /// UaClient Extend + /// + /// Url address of Opc UA server public MyDaClient(Uri serverUrl) : base(serverUrl) { } + /// + /// Unified root node + /// public Node RootNodeBase => RootNode; } + /// + /// DaClient Extend + /// public class MyUaClient : UaClient, IClientExtend { + /// + /// DaClient Extend + /// public MyUaClient(Uri serverUrl) : base(serverUrl) { } + /// + /// Unified root node + /// public Node RootNodeBase => RootNode; } + /// + /// Param input of OpcConnector + /// public class OpcParamIn { + /// + /// Is the action read (not is write) + /// public bool IsRead { get; set; } + + /// + /// Tag of a node + /// public string Tag { get; set; } + + /// + /// Tag splitter of a node + /// public char Split { get; set; } + + /// + /// The value set to node(only available when IsRead is false + /// public object SetValue { get; set; } } + /// + /// Param output of OpcConnector + /// public class OpcParamOut { + /// + /// Is the action success + /// public bool Success { get; set; } + + /// + /// Action return values + /// public byte[] Value { get; set; } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs index 074d867..997c627 100644 --- a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs +++ b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs @@ -3,8 +3,18 @@ using System.Configuration; namespace Modbus.Net.OPC.FBox { + /// + /// FBox的Opc服务设备 + /// public class FBoxOpcDaMachine : OpcDaMachine { + /// + /// 构造函数 + /// + /// 页名称 + /// 设备名称 + /// 获取地址 + /// 是否保持连接 public FBoxOpcDaMachine(string localSequence, string linkerName, IEnumerable getAddresses, bool keepConnect) : base(ConfigurationManager.AppSettings["FBoxOpcDaHost"], getAddresses, keepConnect) @@ -21,14 +31,26 @@ namespace Modbus.Net.OPC.FBox }, this, '.'); } + /// + /// 构造函数 + /// + /// 页名称 + /// 设备名称 + /// 获取地址 public FBoxOpcDaMachine(string localSequence, string linkerName, IEnumerable getAddresses) : this(localSequence, linkerName, getAddresses, false) { } + /// + /// 页名称 + /// public string LocalSequence { get; set; } + /// + /// 设备名称 + /// public string LinkerName { get; set; } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index b4281d5..95ba555 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -9,19 +9,44 @@ using Serilog; namespace Modbus.Net.OPC { + /// + /// Opc连接器 + /// public abstract class OpcConnector : BaseConnector { + /// + /// 是否正在连接 + /// protected bool _connect; + + /// + /// Opc客户端 + /// protected IClientExtend Client; + /// + /// 构造函数 + /// + /// 服务端url protected OpcConnector(string host) { ConnectionToken = host; } + /// + /// 连接标识 + /// public override string ConnectionToken { get; } + + /// + /// 是否正在连接 + /// public override bool IsConnected => _connect; + /// + /// 断开连接 + /// + /// public override bool Disconnect() { try @@ -40,21 +65,43 @@ namespace Modbus.Net.OPC } } + /// + /// 无返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override bool SendMsgWithoutReturn(OpcParamIn message) { throw new NotImplementedException(); } + /// + /// 无返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override Task SendMsgWithoutReturnAsync(OpcParamIn message) { throw new NotImplementedException(); } + /// + /// 带返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override OpcParamOut SendMsg(OpcParamIn message) { return AsyncHelper.RunSync(() => SendMsgAsync(message)); } + /// + /// 根据括号折叠已经打开的标签 + /// + /// 已经打开的标签 + /// 分割符 + /// 开始字符 + /// 结束字符 private void FoldWith(List tagSplitList, char splitChar, char startChar, char endChar) { for (var i = 0; i < tagSplitList.Count; i++) @@ -72,6 +119,12 @@ namespace Modbus.Net.OPC } } + /// + /// 根据分隔符切分标签 + /// + /// 标签 + /// 分隔符 + /// 分割后的标签 private string[] SplitTag(string tag, char split) { var tagSplitList = tag.Split(split).ToList(); @@ -83,6 +136,11 @@ namespace Modbus.Net.OPC return tagSplitList.ToArray(); } + /// + /// 带返回发送数据 + /// + /// 需要发送的数据 + /// 是否发送成功 public override async Task SendMsgAsync(OpcParamIn message) { try @@ -154,6 +212,14 @@ namespace Modbus.Net.OPC } } + /// + /// 搜索标签 + /// + /// 标签 + /// 分隔符 + /// 递归深度(第几级标签) + /// 当前搜索的节点 + /// 搜索到的标签 private async Task SearchTag(string[] tags, char split, int deep, IEnumerable nodes) { foreach (var node in nodes) @@ -170,11 +236,10 @@ namespace Modbus.Net.OPC return null; } - protected void AddInfo(string message) - { - Console.WriteLine(message); - } - + /// + /// 连接PLC + /// + /// 是否连接成功 public override bool Connect() { try @@ -192,6 +257,10 @@ namespace Modbus.Net.OPC } } + /// + /// 连接PLC,异步 + /// + /// 是否连接成功 public override Task ConnectAsync() { return Task.FromResult(Connect()); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs index 4813ef2..416aad5 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs @@ -4,17 +4,29 @@ using System.Collections.Generic; namespace Modbus.Net.OPC { /// - /// OpcDa协议连接实现 + /// Opc DA连接实现 /// public class OpcDaConnector : OpcConnector { + /// + /// DA单例管理 + /// protected static Dictionary _instances = new Dictionary(); + /// + /// 构造函数 + /// + /// Opc DA 服务地址 protected OpcDaConnector(string host) : base(host) { Client = new MyDaClient(new Uri(ConnectionToken)); } + /// + /// 根据服务地址生成DA单例 + /// + /// Opc DA 服务地址 + /// Opc DA 连接器实例 public static OpcDaConnector Instance(string host) { if (!_instances.ContainsKey(host)) diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs index 681fee1..6eed0e3 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs @@ -3,9 +3,20 @@ using System.Collections.Generic; namespace Modbus.Net.OPC { + /// + /// Opc DA设备 + /// + /// 设备Id类型 + /// 设备包含的地址的Id类型 public class OpcDaMachine : OpcMachine where TKey : IEquatable where TUnitKey : IEquatable { + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 + /// 是否保持连接 public OpcDaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { @@ -14,14 +25,28 @@ namespace Modbus.Net.OPC () => ((AddressFormaterOpc) AddressFormater).Seperator; } + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 public OpcDaMachine(string connectionString, IEnumerable> getAddresses) : this(connectionString, getAddresses, false) { } } + /// + /// Opc DA设备 + /// public class OpcDaMachine : OpcMachine { + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 + /// 是否保持连接 public OpcDaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { @@ -30,6 +55,11 @@ namespace Modbus.Net.OPC () => ((AddressFormaterOpc) AddressFormater).Seperator; } + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 public OpcDaMachine(string connectionString, IEnumerable getAddresses) : this(connectionString, getAddresses, false) { diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs index bf5ce6d..41cbdc0 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs @@ -3,29 +3,39 @@ namespace Modbus.Net.OPC { /// - /// OpcDa协议 + /// Opc Da协议 /// public class OpcDaProtocal : OpcProtocal { private readonly string _host; - private int _connectTryCount; + /// + /// 构造函数 + /// + /// Opc DA服务地址 public OpcDaProtocal(string host) { _host = host; } + /// + /// 连接设备 + /// + /// 是否连接成功 public override bool Connect() { return AsyncHelper.RunSync(ConnectAsync); } + /// + /// 连接设备 + /// + /// 是否连接成功 public override async Task ConnectAsync() { - _connectTryCount++; ProtocalLinker = new OpcDaProtocalLinker(_host); - if (!await ProtocalLinker.ConnectAsync()) return false; - _connectTryCount = 0; + if (!await ProtocalLinker.ConnectAsync()) + return false; return true; } } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs index c98b617..7da896b 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs @@ -7,10 +7,17 @@ namespace Modbus.Net.OPC /// public class OpcDaProtocalLinker : OpcProtocalLinker { + /// + /// 构造函数 + /// public OpcDaProtocalLinker() : this(ConfigurationManager.AppSettings["OpcDaHost"]) { } + /// + /// 构造函数 + /// + /// Opc DA服务地址 public OpcDaProtocalLinker(string host) { BaseConnector = OpcDaConnector.Instance(host); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs index d52232d..5415754 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs @@ -5,6 +5,10 @@ /// public class OpcDaUtility : OpcUtility { + /// + /// 构造函数 + /// + /// 连接地址 public OpcDaUtility(string connectionString) : base(connectionString) { Wrapper = new OpcDaProtocal(ConnectionString); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs index 3803e54..0b6f537 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcMachine.cs @@ -4,11 +4,16 @@ using System.Collections.Generic; namespace Modbus.Net.OPC { /// - /// OpcDa设备 + /// Opc Da设备 /// public abstract class OpcMachine : BaseMachine where TKey : IEquatable where TUnitKey : IEquatable { + /// + /// 构造函数 + /// + /// 需要读写的地址 + /// 是否保持连接 protected OpcMachine(IEnumerable> getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { @@ -18,10 +23,15 @@ namespace Modbus.Net.OPC } /// - /// OpcDa设备 + /// Opc Da设备 /// public abstract class OpcMachine : BaseMachine { + /// + /// 构造函数 + /// + /// 需要读写的地址 + /// 是否保持连接 protected OpcMachine(IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs index 6f48d67..ca56811 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs @@ -5,6 +5,9 @@ /// public abstract class OpcProtocal : BaseProtocal> { + /// + /// 构造函数 + /// protected OpcProtocal() : base(0, 0, Endian.BigEndianLsb) { } @@ -12,30 +15,63 @@ #region 读数据 + /// + /// 读数据输入 + /// public class ReadRequestOpcInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 标签 + /// 分隔符 public ReadRequestOpcInputStruct(string tag, char split) { Tag = tag; Split = split; } + /// + /// 标签 + /// public string Tag { get; } + + /// + /// 分隔符 + /// public char Split { get; } } + /// + /// 读地址输出 + /// public class ReadRequestOpcOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 读取的数据 public ReadRequestOpcOutputStruct(byte[] value) { GetValue = value; } + /// + /// 读取的地址 + /// public byte[] GetValue { get; private set; } } + /// + /// 读数据协议 + /// public class ReadRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit { + /// + /// 从对象的参数数组格式化 + /// + /// 非结构化的输入数据 + /// 格式化后的字节流 public override OpcParamIn Format(IInputStruct message) { var r_message = (ReadRequestOpcInputStruct) message; @@ -47,6 +83,12 @@ }; } + /// + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// 结构化的输出数据 public override IOutputStruct Unformat(OpcParamOut messageBytes, ref int pos) { return new ReadRequestOpcOutputStruct(messageBytes.Value); @@ -57,8 +99,17 @@ #region 写数据 + /// + /// 写数据输入 + /// public class WriteRequestOpcInputStruct : IInputStruct { + /// + /// 构造函数 + /// + /// 标签 + /// 分隔符 + /// 写入的数据 public WriteRequestOpcInputStruct(string tag, char split, object setValue) { Tag = tag; @@ -66,23 +117,52 @@ SetValue = setValue; } + /// + /// 标签 + /// public string Tag { get; } + + /// + /// 分隔符 + /// public char Split { get; } + + /// + /// 写入的数据 + /// public object SetValue { get; } } + /// + /// 写数据输出 + /// public class WriteRequestOpcOutputStruct : IOutputStruct { + /// + /// 构造函数 + /// + /// 写入是否成功 public WriteRequestOpcOutputStruct(bool writeResult) { WriteResult = writeResult; } + /// + /// 写入是否成功 + /// public bool WriteResult { get; private set; } } + /// + /// 写数据协议 + /// public class WriteRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit { + /// + /// 从对象的参数数组格式化 + /// + /// 非结构化的输入数据 + /// 格式化后的字节流 public override OpcParamIn Format(IInputStruct message) { var r_message = (WriteRequestOpcInputStruct) message; @@ -95,6 +175,12 @@ }; } + /// + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// 结构化的输出数据 public override IOutputStruct Unformat(OpcParamOut messageBytes, ref int pos) { var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes.Value, ref pos); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs index 8fc4152..498a3e6 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs @@ -4,17 +4,29 @@ using System.Collections.Generic; namespace Modbus.Net.OPC { /// - /// OpcDa协议连接实现 + /// Opc UA连接实现 /// public class OpcUaConnector : OpcConnector { + /// + /// UA单例管理 + /// protected static Dictionary _instances = new Dictionary(); + /// + /// 构造函数 + /// + /// Opc UA 服务地址 protected OpcUaConnector(string host) : base(host) { Client = new MyUaClient(new Uri(ConnectionToken)); } + /// + /// 根据地址获取UA连接器单例 + /// + /// Opc UA服务地址 + /// OPC UA实例 public static OpcUaConnector Instance(string host) { if (!_instances.ContainsKey(host)) diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs index 7e49287..815d482 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs @@ -3,9 +3,20 @@ using System.Collections.Generic; namespace Modbus.Net.OPC { + /// + /// Opc UA设备 + /// + /// 设备Id的类型 + /// 设备中地址的Id的类型 public class OpcUaMachine : OpcMachine where TKey : IEquatable where TUnitKey : IEquatable { + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 + /// 是否保持连接 public OpcUaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { @@ -14,14 +25,28 @@ namespace Modbus.Net.OPC () => ((AddressFormaterOpc) AddressFormater).Seperator; } + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 public OpcUaMachine(string connectionString, IEnumerable> getAddresses) : this(connectionString, getAddresses, false) { } } + /// + /// Opc UA设备 + /// public class OpcUaMachine : OpcMachine { + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 + /// 是否保持连接 public OpcUaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { @@ -30,6 +55,11 @@ namespace Modbus.Net.OPC () => ((AddressFormaterOpc) AddressFormater).Seperator; } + /// + /// 构造函数 + /// + /// 连接地址 + /// 需要读写的数据 public OpcUaMachine(string connectionString, IEnumerable getAddresses) : this(connectionString, getAddresses, false) { diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs index b146880..f358e98 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs @@ -3,29 +3,38 @@ namespace Modbus.Net.OPC { /// - /// OpcUa协议 + /// Opc UA协议 /// public class OpcUaProtocal : OpcProtocal { private readonly string _host; - private int _connectTryCount; + /// + /// 构造函数 + /// + /// Opc UA服务地址 public OpcUaProtocal(string host) { _host = host; } + /// + /// 连接设备 + /// + /// 是否连接成功 public override bool Connect() { return AsyncHelper.RunSync(ConnectAsync); } + /// + /// 连接设备 + /// + /// 是否连接成功 public override async Task ConnectAsync() { - _connectTryCount++; ProtocalLinker = new OpcUaProtocalLinker(_host); if (!await ProtocalLinker.ConnectAsync()) return false; - _connectTryCount = 0; return true; } } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs index 31b3279..34dc6cb 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs @@ -3,14 +3,21 @@ namespace Modbus.Net.OPC { /// - /// Opc Da协议连接器 + /// Opc UA协议连接器 /// public class OpcUaProtocalLinker : OpcProtocalLinker { + /// + /// 构造函数 + /// public OpcUaProtocalLinker() : this(ConfigurationManager.AppSettings["OpcUaHost"]) { } + /// + /// 构造函数 + /// + /// Opc UA服务地址 public OpcUaProtocalLinker(string host) { BaseConnector = OpcUaConnector.Instance(host); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs index e061c28..e144afe 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs @@ -1,10 +1,14 @@ namespace Modbus.Net.OPC { /// - /// Opc Da协议Api入口 + /// Opc Ua协议Api入口 /// public class OpcUaUtility : OpcUtility { + /// + /// 构造函数 + /// + /// 连接地址 public OpcUaUtility(string connectionString) : base(connectionString) { Wrapper = new OpcUaProtocal(ConnectionString); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index 8da536b..050b2e6 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -4,25 +4,52 @@ using Serilog; namespace Modbus.Net.OPC { + /// + /// Opc通用Api入口 + /// public abstract class OpcUtility : BaseUtility> { + /// + /// 获取分隔符 + /// + /// 分隔符 public delegate char GetSeperatorDelegate(); + /// + /// 构造函数 + /// + /// 连接地址 protected OpcUtility(string connectionString) : base(0, 0) { ConnectionString = connectionString; AddressTranslator = new AddressTranslatorOpc(); } + /// + /// 端格式(大端) + /// public override Endian Endian => Endian.BigEndianLsb; + /// + /// 获取分隔符 + /// public event GetSeperatorDelegate GetSeperator; + /// + /// 设置连接方式(Opc忽略该函数) + /// + /// 连接方式 public override void SetConnectionType(int connectionType) { - throw new NotImplementedException(); + //ignore } + /// + /// 获取数据 + /// + /// 开始地址 + /// 获取字节数个数 + /// 接收到的byte数据 public override async Task GetDatasAsync(string startAddress, int getByteCount) { try @@ -42,6 +69,12 @@ namespace Modbus.Net.OPC } } + /// + /// 设置数据 + /// + /// 开始地址 + /// 设置数据 + /// 是否设置成功 public override async Task SetDatasAsync(string startAddress, object[] setContents) { try From df94010952bf2a34073946ca4ae481b4db4a9d50 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 18 May 2017 18:51:01 +0800 Subject: [PATCH 19/62] Bug Fix --- Modbus.Net/src/Base.Common/BaseMachine.cs | 4 +-- Modbus.Net/src/Base.Common/BaseProtocal.cs | 21 ++++++------ Modbus.Net/src/Base.Common/TaskManager.cs | 37 +++++++++++++++------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 8331af7..0afc244 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -413,13 +413,13 @@ namespace Modbus.Net //地址为空报错 if (address == null) { - Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} doesn't exist."); + Log.Error($"Machine {ConnectionToken} Address {value.Key} doesn't exist."); continue; } //不能写报错 if (!address.CanWrite) { - Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} cannot write."); + Log.Error($"Machine {ConnectionToken} Address {value.Key} cannot write."); continue; } addresses.Add(address); diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 2d90475..1ab664a 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -80,15 +80,18 @@ namespace Modbus.Net get { var protocalName = type.FullName; - if (Protocals.ContainsKey(protocalName)) - return Protocals[protocalName]; - //自动寻找存在的协议并将其加载 - var protocalUnit = - Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; - if (protocalUnit == null) - throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented"); - protocalUnit.Endian = Endian; - Register(protocalUnit); + lock (Protocals) + { + if (Protocals.ContainsKey(protocalName)) + return Protocals[protocalName]; + //自动寻找存在的协议并将其加载 + var protocalUnit = + Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; + if (protocalUnit == null) + throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented"); + protocalUnit.Endian = Endian; + Register(protocalUnit); + } return Protocals[protocalName]; } } diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 22305db..a36638c 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -418,10 +418,10 @@ namespace Modbus.Net var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(100000)); var ans = - await tasks.Run( + await tasks.StartNew( async () => await machine.InvokeMachineMethod>>("GetDatasAsync", - MachineGetDataType.CommunicationTag).WithCancellation(cts.Token)); + MachineGetDataType.CommunicationTag).WithCancellation(cts.Token)).Unwrap(); return new DataReturnDef { MachineId = machine.GetMachineIdString(), @@ -453,10 +453,10 @@ namespace Modbus.Net var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(100000)); var ans = - await tasks.Run( + await tasks.StartNew( async () => await machine.InvokeMachineMethod>("SetDatasAsync", parameters[0], - MachineSetDataType.CommunicationTag).WithCancellation(cts.Token)); + MachineSetDataType.CommunicationTag).WithCancellation(cts.Token)).Unwrap(); return ans; }; Params = new object[] {values}; @@ -468,7 +468,7 @@ namespace Modbus.Net /// 任务 /// /// 任务返回值的类型 - public class TaskItem : ITaskItem, IEquatable> + public class TaskItem : ITaskItem, IEquatable>, ICloneable { /// /// 定时器 @@ -574,7 +574,7 @@ namespace Modbus.Net /// private void DeactivateTimer() { - Timer.Dispose(); + Timer?.Dispose(); Timer = null; } @@ -595,7 +595,7 @@ namespace Modbus.Net /// private void DeactivateTimerDisconnected() { - TimerDisconnected.Dispose(); + TimerDisconnected?.Dispose(); TimerDisconnected = null; } @@ -620,6 +620,15 @@ namespace Modbus.Net ActivateTimerDisconnected(); return true; } + + /// + /// 拷贝实例 + /// + /// 拷贝的实例 + public object Clone() + { + return MemberwiseClone(); + } } /// @@ -943,7 +952,10 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - ans &= machine.InvokeTimer(item); + { + Thread.Sleep(10); + ans &= machine.InvokeTimer(item.Clone() as TaskItem); + } } return ans; } @@ -958,7 +970,10 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) + { + Thread.Sleep(10); ans &= machine.StopAllTimers(); + } } return ans; } @@ -1052,7 +1067,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - tasks.Add(machine.InvokeOnce(item)); + tasks.Add(_tasks.StartNew(async () => await machine.InvokeOnce(item.Clone() as TaskItem)).Unwrap()); } var ans = await Task.WhenAll(tasks); return ans.All(p => p); @@ -1069,7 +1084,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - return await machine.InvokeOnce(item); + return await machine.InvokeOnce(item.Clone() as TaskItem); return false; } @@ -1084,7 +1099,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - return machine.InvokeTimer(item); + return machine.InvokeTimer(item.Clone() as TaskItem); return false; } From 3ff11e9b3d88abf9b5f62e93f47dd84b1a07c33e Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 18 May 2017 19:03:07 +0800 Subject: [PATCH 20/62] Remove a comment --- Modbus.Net/src/Base.Common/BaseMachine.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index 0afc244..f9de1f3 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -670,7 +670,6 @@ namespace Modbus.Net { public bool Equals(IMachineProperty x, IMachineProperty y) { - //1.3版本中需要修改这句话 return x.Id.Equals(y.Id) || x.ConnectionToken == y.ConnectionToken; } From 9305cade9e27d17794de5a1b448c89e026833d83 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 18 May 2017 21:17:03 +0800 Subject: [PATCH 21/62] Bug Fix. --- Modbus.Net/src/Base.Common/BaseMachine.cs | 2 +- Modbus.Net/src/Base.Common/TaskManager.cs | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index f9de1f3..ee97b51 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -670,7 +670,7 @@ namespace Modbus.Net { public bool Equals(IMachineProperty x, IMachineProperty y) { - return x.Id.Equals(y.Id) || x.ConnectionToken == y.ConnectionToken; + return x.Id.Equals(y.Id); } public int GetHashCode(IMachineProperty obj) diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index a36638c..dd3bf71 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -847,11 +847,8 @@ namespace Modbus.Net public void AddMachines(IEnumerable> machines) where TUnitKey : IEquatable { - lock (_machines) - { - foreach (var machine in machines) - AddMachine(machine); - } + foreach (var machine in machines) + AddMachine(machine); } /// @@ -868,13 +865,13 @@ namespace Modbus.Net TaskMachine machine; lock (_machines) { - machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(id)); + machine = _machines.SingleOrDefault(p => p.Machine.Id.Equals(id)); } - return machine as BaseMachine; + return machine?.Machine as BaseMachine; } catch (Exception e) { - Log.Error(e, $"Device {id} return error"); + Log.Error(e, $"Device {id} get error, maybe duplicated in taskmanager"); return null; } } @@ -893,13 +890,13 @@ namespace Modbus.Net TaskMachine machine; lock (_machines) { - machine = _machines.FirstOrDefault(p => p.Machine.ConnectionToken == connectionToken); + machine = _machines.SingleOrDefault(p => p.Machine.ConnectionToken == connectionToken && p.Machine.IsConnected); } - return machine as BaseMachine; + return machine?.Machine as BaseMachine; } catch (Exception e) { - Log.Error(e, $"Device {connectionToken} return error"); + Log.Error(e, $"Device {connectionToken} get error, maybe duplicated in taskmanager"); return null; } } From b558a57248587d330e10e9701aa4aa1ecf274ebe Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 18 May 2017 22:04:59 +0800 Subject: [PATCH 22/62] Bug Fix --- Modbus.Net/src/Base.Common/TaskManager.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index dd3bf71..c7dbe25 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -468,7 +468,7 @@ namespace Modbus.Net /// 任务 /// /// 任务返回值的类型 - public class TaskItem : ITaskItem, IEquatable>, ICloneable + public class TaskItem : ITaskItem, IEquatable> { /// /// 定时器 @@ -625,9 +625,9 @@ namespace Modbus.Net /// 拷贝实例 /// /// 拷贝的实例 - public object Clone() + public TaskItem Clone() { - return MemberwiseClone(); + return MemberwiseClone() as TaskItem; } } @@ -951,7 +951,7 @@ namespace Modbus.Net foreach (var machine in _machines) { Thread.Sleep(10); - ans &= machine.InvokeTimer(item.Clone() as TaskItem); + ans &= machine.InvokeTimer(item.Clone()); } } return ans; @@ -1064,7 +1064,7 @@ namespace Modbus.Net lock (_machines) { foreach (var machine in _machines) - tasks.Add(_tasks.StartNew(async () => await machine.InvokeOnce(item.Clone() as TaskItem)).Unwrap()); + tasks.Add(_tasks.StartNew(async () => await machine.InvokeOnce(item.Clone())).Unwrap()); } var ans = await Task.WhenAll(tasks); return ans.All(p => p); @@ -1081,7 +1081,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - return await machine.InvokeOnce(item.Clone() as TaskItem); + return await machine.InvokeOnce(item.Clone()); return false; } @@ -1096,7 +1096,7 @@ namespace Modbus.Net { var machine = _machines.FirstOrDefault(p => p.Machine.Id.Equals(machineId)); if (machine != null) - return machine.InvokeTimer(item.Clone() as TaskItem); + return machine.InvokeTimer(item.Clone()); return false; } From 189dff08a7ebd387a241f2e3c45387f427e4cda7 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 19 May 2017 10:41:41 +0800 Subject: [PATCH 23/62] Bug Fix --- Modbus.Net/src/Base.Common/BaseProtocal.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 1ab664a..3873ac5 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -80,10 +80,11 @@ namespace Modbus.Net get { var protocalName = type.FullName; + TProtocalUnit protocalUnitReturn = null; lock (Protocals) { if (Protocals.ContainsKey(protocalName)) - return Protocals[protocalName]; + protocalUnitReturn = Protocals[protocalName]; //自动寻找存在的协议并将其加载 var protocalUnit = Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; @@ -92,7 +93,7 @@ namespace Modbus.Net protocalUnit.Endian = Endian; Register(protocalUnit); } - return Protocals[protocalName]; + return protocalUnitReturn ?? Protocals[protocalName]; } } From 84e144f15bc76f3fa045e07f568d516b590cecab Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 19 May 2017 10:42:40 +0800 Subject: [PATCH 24/62] Bug Fix --- Modbus.Net/src/Base.Common/BaseProtocal.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 3873ac5..c31b6ce 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -85,13 +85,16 @@ namespace Modbus.Net { if (Protocals.ContainsKey(protocalName)) protocalUnitReturn = Protocals[protocalName]; - //自动寻找存在的协议并将其加载 - var protocalUnit = - Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; - if (protocalUnit == null) - throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented"); - protocalUnit.Endian = Endian; - Register(protocalUnit); + else + { + //自动寻找存在的协议并将其加载 + var protocalUnit = + Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; + if (protocalUnit == null) + throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented"); + protocalUnit.Endian = Endian; + Register(protocalUnit); + } } return protocalUnitReturn ?? Protocals[protocalName]; } From 444fdcd142f1cdff5d6fe1a3d965ba2abe79490f Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 19 May 2017 15:41:35 +0800 Subject: [PATCH 25/62] Version Update --- Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj | 2 +- Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj | 2 +- Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj | 2 +- Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj | 2 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 0578162..1752996 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.2 + 1.3.8-beta1 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index d0c29f2..d1d931b 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.2 + 1.3.8-beta1 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index 3f38142..ecd4875 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.2 + 1.3.8-beta1 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net OPC Implementation diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 3c27504..2665b5d 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.2 + 1.3.8-beta1 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net Siemens Profinet Implementation diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index ef209ac..ffd5b50 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.2 + 1.3.8-beta1 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. From 3518fa3338594b4265e315c92578c18b8235af1e Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 19 May 2017 16:37:54 +0800 Subject: [PATCH 26/62] Add roadmaps. --- Modbus.Net/Modbus.Net/README.md | 2 +- README.md | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Modbus.Net/Modbus.Net/README.md b/Modbus.Net/Modbus.Net/README.md index fac42f7..f096d6d 100644 --- a/Modbus.Net/Modbus.Net/README.md +++ b/Modbus.Net/Modbus.Net/README.md @@ -20,7 +20,7 @@ Table of Content: * OPC DA protocal. * All communications could be asynchronized. * A task manager that you can easily manage multiple connections. -* .NET Framework 4.5 and Visual Studio 2015 support. +* .NET Framework 4.5 and Visual Studio 2017 support. ## Usage diff --git a/README.md b/README.md index 97f4b86..4aacd09 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,36 @@ Platform Supported * OPC Regex comparer for tags (Complete) ### Version 1.3.0 -* .NET Core Support (Not Test) +* .NET Core Support (Complete) +* Fix a bug in BaseMachine (Complete) + +### Version 1.3.1 +* InputStruct -> IInputStruct, OutputStruct -> IOutputStruct (Complete) +* Generic Method For ProtocalUnit (Complete) + +### Version 1.3.2 +* Add Interface IMachineMethod and IUtilityMethod. Utiltiy and Machine can extend function using interface (Not Tested) + +### Version 1.3.3 +* TaskManager Remake (Not Tested) + +### Version 1.3.4 +* A Serial Port now can connect to multiple machines using same protocol with different slave address (Not Tested) + +### Version 1.3.5 +* New log system using serilog (Not Tested) + +### Version 1.3.6 +* Add gereric Type for BaseConnector, now protocol developer can pass any type to BaseConnector not only byte[] (Not Tested) +* Add more gereric types in Modbus.Net to support this function (Not Tested) +* Add more interfaces to make them completed in Modbus.Net (Not Tested) +* Support this function in Modbus.Net.OPC (Not Tested) + +### Version 1.3.7 +* AddressCombiner need to add maximum length now. Combiner will consider the maximum length when combining addresses (Not Tested) + +### Version 1.3.8 +* Change Resx to app.config or appsettings.json, now you can set default params there (Not Tested) ### Version 1.4.0 * New Protocal Pipeline System (In Road) From 3965ced0c25f77acfd95260e0b1c93b8ff23a220 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Mon, 22 May 2017 10:29:46 +0800 Subject: [PATCH 27/62] Project Bug Fix --- Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj | 2 +- Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj | 2 +- Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj | 2 +- Modbus.Net/Modbus.Net.sln | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index d1d931b..93e0701 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -24,7 +24,7 @@ - + diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index ecd4875..02d839e 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -28,7 +28,7 @@ - + diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 2665b5d..68e6b31 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -23,7 +23,7 @@ - + diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln index cca2cc0..f213f2a 100644 --- a/Modbus.Net/Modbus.Net.sln +++ b/Modbus.Net/Modbus.Net.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26403.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net", "ModBus.Net\Modbus.Net.csproj", "{124EBEF2-8960-4447-84CF-1D683B1EF7CC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net", "Modbus.Net\Modbus.Net.csproj", "{124EBEF2-8960-4447-84CF-1D683B1EF7CC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{64472271-8B95-4036-ACF9-C10941C1DB0A}" ProjectSection(SolutionItems) = preProject From 27069863814bca21cd2c2056050fc22916f60ba0 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 10:07:37 +0800 Subject: [PATCH 28/62] Bug Fix. --- Modbus.Net/src/Base.Common/BaseMachine.cs | 42 +++++++++----- Modbus.Net/src/Base.Common/TaskManager.cs | 68 +++-------------------- 2 files changed, 36 insertions(+), 74 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index ee97b51..e247760 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -304,24 +304,36 @@ namespace Modbus.Net } } - //如果没有数据返回空 - if (datas.Length == 0) - ans.Add(key, new ReturnUnit - { - PlcValue = null, - UnitExtend = address.UnitExtend - }); - else - ans.Add(key, - new ReturnUnit + try + { + //如果没有数据返回空 + if (datas.Length == 0) + ans.Add(key, new ReturnUnit { - PlcValue = - Convert.ToDouble( - ValueHelper.GetInstance(BaseUtility.Endian) - .GetValue(datas, ref localMainPos, ref localSubPos, - address.DataType)) * address.Zoom, + PlcValue = null, UnitExtend = address.UnitExtend }); + else + ans.Add(key, + new ReturnUnit + { + PlcValue = + Convert.ToDouble( + ValueHelper.GetInstance(BaseUtility.Endian) + .GetValue(datas, ref localMainPos, ref localSubPos, + address.DataType)) * address.Zoom, + UnitExtend = address.UnitExtend + }); + } + catch (Exception e) + { + ErrorCount++; + Log.Error(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} key {key} existing. ErrorCount {ErrorCount}."); + + if (ErrorCount >= _maxErrorCount) + Disconnect(); + return null; + } } } //如果不保持连接,断开连接 diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index c7dbe25..0e876b1 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -408,9 +408,10 @@ namespace Modbus.Net /// 构造函数 /// /// 返回值的处理函数 + /// 返回值的键类型 /// 循环间隔(毫秒) /// 设备离线时的循环间隔(毫秒) - public TaskItemGetData(Action returnFunc, int getCycle, int sleepCycle) + public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle, int sleepCycle) { Name = "GetDatas"; Invoke = async (machine, tasks, parameters) => @@ -421,7 +422,7 @@ namespace Modbus.Net await tasks.StartNew( async () => await machine.InvokeMachineMethod>>("GetDatasAsync", - MachineGetDataType.CommunicationTag).WithCancellation(cts.Token)).Unwrap(); + getDataType).WithCancellation(cts.Token)).Unwrap(); return new DataReturnDef { MachineId = machine.GetMachineIdString(), @@ -444,8 +445,9 @@ namespace Modbus.Net /// 构造函数 /// /// 写入的值 + /// 写入值的键类型 /// 返回值的处理函数 - public TaskItemSetData(Dictionary values, Action returnFunc = null) + public TaskItemSetData(Dictionary values, MachineSetDataType setDataType, Action returnFunc = null) { Name = "SetDatas"; Invoke = Invoke = async (machine, tasks, parameters) => @@ -456,7 +458,7 @@ namespace Modbus.Net await tasks.StartNew( async () => await machine.InvokeMachineMethod>("SetDatasAsync", parameters[0], - MachineSetDataType.CommunicationTag).WithCancellation(cts.Token)).Unwrap(); + setDataType).WithCancellation(cts.Token)).Unwrap(); return ans; }; Params = new object[] {values}; @@ -641,10 +643,8 @@ namespace Modbus.Net /// /// 同时可以运行的任务数 /// 读取数据后是否保持连接 - /// 获取与设置数据的方式 - public TaskManager(int maxRunningTask, bool keepConnect, - MachineDataType dataType = MachineDataType.CommunicationTag) - : base(maxRunningTask, keepConnect, dataType) + public TaskManager(int maxRunningTask, bool keepConnect) + : base(maxRunningTask, keepConnect) { } @@ -723,15 +723,12 @@ namespace Modbus.Net /// /// 同时可以运行的任务数 /// 读取数据后是否保持连接 - /// 获取与设置数据的方式 - public TaskManager(int maxRunningTask, bool keepConnect, - MachineDataType dataType = MachineDataType.CommunicationTag) + public TaskManager(int maxRunningTask, bool keepConnect) { _scheduler = new LimitedConcurrencyLevelTaskScheduler(maxRunningTask); _machines = new HashSet>(new TaskMachineEqualityComparer()); KeepConnect = keepConnect; - MachineDataType = dataType; _cts = new CancellationTokenSource(); _tasks = new TaskFactory(_cts.Token, TaskCreationOptions.None, TaskContinuationOptions.None, _scheduler); } @@ -755,53 +752,6 @@ namespace Modbus.Net } } - /// - /// 设备读写设备的关键字 - /// - public MachineDataType MachineDataType - { - set - { - switch (value) - { - case MachineDataType.Address: - { - GetDataType = MachineGetDataType.Address; - SetDataType = MachineSetDataType.Address; - break; - } - case MachineDataType.CommunicationTag: - { - GetDataType = MachineGetDataType.CommunicationTag; - SetDataType = MachineSetDataType.CommunicationTag; - break; - } - case MachineDataType.Name: - { - GetDataType = MachineGetDataType.Name; - SetDataType = MachineSetDataType.Name; - break; - } - case MachineDataType.Id: - { - GetDataType = MachineGetDataType.Id; - SetDataType = MachineSetDataType.Id; - break; - } - } - } - } - - /// - /// 设备读数据的关键字 - /// - public MachineGetDataType GetDataType { get; set; } - - /// - /// 设备写数据的关键字 - /// - public MachineSetDataType SetDataType { get; set; } - /// /// 最大可执行任务数 /// From bedf8c9b284ccb9d9918d742ec89997c201f1602 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 11:22:27 +0800 Subject: [PATCH 29/62] Fix a bug in AddressCombinerNumericJump --- Modbus.Net/src/Base.Common/AddressCombiner.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modbus.Net/src/Base.Common/AddressCombiner.cs b/Modbus.Net/src/Base.Common/AddressCombiner.cs index 305fb93..5c66dde 100644 --- a/Modbus.Net/src/Base.Common/AddressCombiner.cs +++ b/Modbus.Net/src/Base.Common/AddressCombiner.cs @@ -351,7 +351,8 @@ namespace Modbus.Net { if (orderedGap.GapNumber <= 0) continue; var nowAddress = orderedGap.EndUnit; - var index = continusAddresses.IndexOf(nowAddress); + var index = continusAddresses.FindIndex(p=>p.Area == nowAddress.Area && p.Address == nowAddress.Address && p.SubAddress == nowAddress.SubAddress); + nowAddress = continusAddresses[index]; index--; var preAddress = continusAddresses[index]; if (nowAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName] + From 69603827129269b5ce5849fef6d96c3fadfbaf74 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 12:32:59 +0800 Subject: [PATCH 30/62] Add two verbose messages in OPC --- Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index 95ba555..e9d42d4 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -155,6 +155,7 @@ namespace Modbus.Net.OPC if (answerTag != null) { var result = await Client.ReadAsync(answerTag); + Log.Verbose($"Opc Machine {ConnectionToken} Read opc tag {answerTag} for value {result}"); return new OpcParamOut { Success = true, @@ -181,6 +182,7 @@ namespace Modbus.Net.OPC try { await Client.WriteAsync(answerTag, value); + Log.Verbose($"Opc Machine {ConnectionToken} Write opc tag {answerTag} for value {value}"); } catch (Exception e) { From a546e6d77ce52da0afe0f49b3e05f44507142d44 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 15:07:27 +0800 Subject: [PATCH 31/62] Change ISpecialProtocalUnit to SpecialProtocalUnitAttribute --- Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs | 6 ++++-- Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs | 9 ++++++--- Modbus.Net/Modbus.Net/README.md | 7 ++++--- Modbus.Net/src/Base.Common/BaseProtocal.cs | 3 ++- Modbus.Net/src/Base.Common/ProtocalUnit.cs | 3 ++- Samples/AnyType/Controllers/HomeController.cs | 2 +- Samples/TaskManager/Controllers/HomeController.cs | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) 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..fea5f5d 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; @@ -185,7 +186,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); 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/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] From fa8dbf9fd3c437f7ef6ce641c56bff89b0b9d55b Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 16:24:51 +0800 Subject: [PATCH 32/62] Change TParamOut to class --- Modbus.Net/src/Base.Common/BaseProtocal.cs | 2 +- Modbus.Net/src/Base.Common/BaseUtility.cs | 2 +- Modbus.Net/src/Base.Common/ProtocalLinker.cs | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index fea5f5d..08473da 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -38,7 +38,7 @@ namespace Modbus.Net /// 基本协议 /// public abstract class BaseProtocal : - IProtocal where TProtocalUnit : ProtocalUnit + IProtocal where TProtocalUnit : ProtocalUnit where TParamOut : class { /// /// 构造器 diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index ddb7331..3b069dd 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -44,7 +44,7 @@ namespace Modbus.Net /// 基础Api入口 /// public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData - where TProtocalUnit : ProtocalUnit + where TProtocalUnit : ProtocalUnit where TParamOut : class { /// /// 协议收发主体 diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index bd7accd..c66290d 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -70,7 +70,7 @@ namespace Modbus.Net /// /// 基本的协议连接器 /// - public abstract class ProtocalLinker : IProtocalLinker + public abstract class ProtocalLinker : IProtocalLinker where TParamOut : class { /// /// 传输连接器 @@ -106,8 +106,7 @@ namespace Modbus.Net { var extBytes = BytesExtend(content); var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); - if (receiveBytes != null) return receiveBytes; - throw new NullReferenceException(); + return receiveBytes; } /// @@ -132,8 +131,7 @@ namespace Modbus.Net //容错处理 var checkRight = CheckRight(receiveBytes); //返回字符 - if (checkRight == true) return receiveBytes; - throw new NullReferenceException(); + return checkRight == true ? receiveBytes : null; } /// From 79759b5a5d5fcd19469c6a3083859ccf187b4457 Mon Sep 17 00:00:00 2001 From: "Chris L.(Luo Sheng)" Date: Tue, 23 May 2017 16:30:37 +0800 Subject: [PATCH 33/62] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) 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) From 96f14377dc26c52b6b65847b356c35a8b1391cfd Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 16:54:04 +0800 Subject: [PATCH 34/62] Fix --- Modbus.Net/src/Base.Common/ProtocalLinker.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index c66290d..783e879 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -106,7 +106,7 @@ namespace Modbus.Net { var extBytes = BytesExtend(content); var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); - return receiveBytes; + return BytesDecact(receiveBytes); } /// @@ -151,20 +151,14 @@ namespace Modbus.Net /// /// 扩展前的基本协议内容 /// 扩展后的协议内容 - public virtual TParamIn BytesExtend(TParamIn content) - { - throw new NotImplementedException(); - } + public abstract TParamIn BytesExtend(TParamIn content); /// /// 协议内容缩减,接收时根据需要缩减 /// /// 缩减前的完整协议内容 /// 缩减后的协议内容 - public virtual TParamOut BytesDecact(TParamOut content) - { - throw new NotImplementedException(); - } + public abstract TParamOut BytesDecact(TParamOut content); /// /// 连接设备 From 156b8a370b374d8a09d8e59cee219eb323d847a1 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 17:32:50 +0800 Subject: [PATCH 35/62] Use Interfaces --- Modbus.Net/src/Base.Common/BaseProtocal.cs | 77 ++++++++++--------- Modbus.Net/src/Base.Common/BaseUtility.cs | 2 +- Modbus.Net/src/Base.Common/IProtocal.cs | 63 +++++++++++++-- Modbus.Net/src/Base.Common/IProtocalLinker.cs | 28 +++++++ Modbus.Net/src/Base.Common/ProtocalLinker.cs | 63 ++++++++------- 5 files changed, 160 insertions(+), 73 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 08473da..155ce91 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -38,7 +38,8 @@ namespace Modbus.Net /// 基本协议 /// public abstract class BaseProtocal : - IProtocal where TProtocalUnit : ProtocalUnit where TParamOut : class + IProtocal where TProtocalUnit : ProtocalUnit + where TParamOut : class { /// /// 构造器 @@ -67,9 +68,9 @@ namespace Modbus.Net public byte MasterAddress { get; set; } /// - /// 协议的连接器 + /// 协议集合 /// - public ProtocalLinker ProtocalLinker { get; protected set; } + protected Dictionary Protocals { get; } /// /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 @@ -85,7 +86,9 @@ namespace Modbus.Net lock (Protocals) { if (Protocals.ContainsKey(protocalName)) + { protocalUnitReturn = Protocals[protocalName]; + } else { //自动寻找存在的协议并将其加载 @@ -95,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; + } /// /// 发送协议,通过传入需要使用的协议内容和输入结构 @@ -133,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); - } - /// /// 发送协议,通过传入需要使用的协议内容和输入结构 /// @@ -197,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 3b069dd..f7ede9e 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -49,7 +49,7 @@ namespace Modbus.Net /// /// 协议收发主体 /// - 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/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 783e879..9c9716c 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -70,13 +70,41 @@ namespace Modbus.Net /// /// 基本的协议连接器 /// - public abstract class ProtocalLinker : IProtocalLinker where TParamOut : class + 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(); + } + /// /// 通讯字符串 /// @@ -151,40 +179,19 @@ namespace Modbus.Net /// /// 扩展前的基本协议内容 /// 扩展后的协议内容 - public abstract TParamIn BytesExtend(TParamIn content); + public virtual TParamIn BytesExtend(TParamIn content) + { + throw new NotImplementedException(); + } /// /// 协议内容缩减,接收时根据需要缩减 /// /// 缩减前的完整协议内容 /// 缩减后的协议内容 - public abstract TParamOut BytesDecact(TParamOut content); - - /// - /// 连接设备 - /// - /// 设备是否连接成功 - public bool Connect() + public virtual TParamOut BytesDecact(TParamOut content) { - return BaseConnector.Connect(); - } - - /// - /// 连接设备 - /// - /// 设备是否连接成功 - public async Task ConnectAsync() - { - return await BaseConnector.ConnectAsync(); - } - - /// - /// 断开设备 - /// - /// 设备是否断开成功 - public bool Disconnect() - { - return BaseConnector.Disconnect(); + throw new NotImplementedException(); } } } \ No newline at end of file From da0c5fcb846f3236b2a36f3be164b9b0f31cdcac Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Tue, 23 May 2017 17:41:52 +0800 Subject: [PATCH 36/62] Use interfaces --- Modbus.Net/src/Base.Common/BaseProtocal.cs | 2 +- Modbus.Net/src/Base.Common/BaseUtility.cs | 2 +- Modbus.Net/src/Base.Common/IProtocalFormatting.cs | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index 155ce91..0f7acfb 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -38,7 +38,7 @@ namespace Modbus.Net /// 基本协议 /// public abstract class BaseProtocal : - IProtocal where TProtocalUnit : ProtocalUnit + IProtocal where TProtocalUnit : class, IProtocalFormatting where TParamOut : class { /// diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index f7ede9e..fb1cd9b 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -44,7 +44,7 @@ namespace Modbus.Net /// 基础Api入口 /// public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData - where TProtocalUnit : ProtocalUnit where TParamOut : class + where TProtocalUnit : class, IProtocalFormatting where TParamOut : class { /// /// 协议收发主体 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; } + /// /// 从输入结构格式化 /// From 249d20a17a6f9d9e813b6e634ebdd8e8dc8552a7 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 09:41:02 +0800 Subject: [PATCH 37/62] Add timeout param. --- Modbus.Net/src/Base.Common/TaskManager.cs | 27 +++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 0e876b1..b1d5d6c 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -354,7 +354,7 @@ namespace Modbus.Net { if (Machine.IsConnected) { - var ans = await task.Invoke(Machine, _tasks, task.Params); + var ans = await task.Invoke(Machine, _tasks, task.Params, task.TimeoutTime); task.Return?.Invoke(ans); return true; } @@ -411,13 +411,15 @@ namespace Modbus.Net /// 返回值的键类型 /// 循环间隔(毫秒) /// 设备离线时的循环间隔(毫秒) - public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle, int sleepCycle) + /// 任务的超时时间 + public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle, int sleepCycle, int timeout = 100000) { Name = "GetDatas"; - Invoke = async (machine, tasks, parameters) => + TimeoutTime = timeout; + Invoke = async (machine, tasks, parameters, timeoutTime) => { var cts = new CancellationTokenSource(); - cts.CancelAfter(TimeSpan.FromSeconds(100000)); + cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); var ans = await tasks.StartNew( async () => await machine.InvokeMachineMethod写入的值 /// 写入值的键类型 /// 返回值的处理函数 - public TaskItemSetData(Dictionary values, MachineSetDataType setDataType, Action returnFunc = null) + /// 任务的超时时间 + public TaskItemSetData(Dictionary values, MachineSetDataType setDataType, Action returnFunc = null, int timeout = 100000) { Name = "SetDatas"; - Invoke = Invoke = async (machine, tasks, parameters) => + TimeoutTime = timeout; + Invoke = Invoke = async (machine, tasks, parameters, timeoutTime) => { var cts = new CancellationTokenSource(); - cts.CancelAfter(TimeSpan.FromSeconds(100000)); + cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); var ans = await tasks.StartNew( async () => await machine.InvokeMachineMethod public int TimerTime { get; set; } + /// + /// 超时时间 + /// + public int TimeoutTime { get; set; } = 100000; + /// /// 离线定时器 /// @@ -495,7 +504,7 @@ namespace Modbus.Net /// /// 执行的任务 /// - public Func> Invoke { get; set; } + public Func> Invoke { get; set; } /// /// 检测设备的在线状态 @@ -566,7 +575,7 @@ namespace Modbus.Net Timer = new Timer(async state => { if (!DetectConnected()) TimerChangeToDisconnect(); - var ans = await Invoke(GetMachine(), GetTaskFactory(), Params); + var ans = await Invoke(GetMachine(), GetTaskFactory(), Params, TimeoutTime); Return?.Invoke(ans); }, null, 0, TimerTime); } From c23f00b69e7017832cf4a555cda3a28a5ad98c5d Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 11:42:52 +0800 Subject: [PATCH 38/62] 2017-05-24 Update 1 Test Fix --- Tests/Modbus.Net.Tests/App.config | 6 ++ Tests/Modbus.Net.Tests/BaseTest.cs | 6 +- .../Modbus.Net.Tests/Modbus.Net.Tests.csproj | 3 + Tests/Modbus.Net.Tests/ModbusTest.cs | 55 +++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 Tests/Modbus.Net.Tests/App.config diff --git a/Tests/Modbus.Net.Tests/App.config b/Tests/Modbus.Net.Tests/App.config new file mode 100644 index 0000000..7802c78 --- /dev/null +++ b/Tests/Modbus.Net.Tests/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Tests/Modbus.Net.Tests/BaseTest.cs b/Tests/Modbus.Net.Tests/BaseTest.cs index 46cb258..9a17f52 100644 --- a/Tests/Modbus.Net.Tests/BaseTest.cs +++ b/Tests/Modbus.Net.Tests/BaseTest.cs @@ -135,13 +135,15 @@ namespace Modbus.Net.Tests ProjectName = "Project 1", MachineName = "Test 1" }; - _baseMachine2 = new SiemensMachine(SiemensType.Tcp, "192.168.1.2", SiemensMachineModel.S7_300, _addressUnits, true, 2, 0) + _baseMachine2 = new SiemensMachine(SiemensType.Tcp, "192.168.3.10", SiemensMachineModel.S7_1200, _addressUnits, true, 2, 0) { Id = 2, ProjectName = "Project 1", MachineName = "Test 2" }; + _baseMachine2.Connect(); + _taskManager = new TaskManager(10, true); _taskManager.AddMachine(_baseMachine); @@ -313,7 +315,7 @@ namespace Modbus.Net.Tests var machine = _taskManager.GetMachineById(1); Assert.AreEqual(machine.MachineName, "Test 1"); - var machine2 = _taskManager.GetMachineByConnectionToken("192.168.1.2"); + var machine2 = _taskManager.GetMachineByConnectionToken("192.168.3.10"); Assert.AreEqual(machine2.MachineName, "Test 2"); } diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index a3c5572..454edec 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -78,6 +78,9 @@ Modbus.Net + + + diff --git a/Tests/Modbus.Net.Tests/ModbusTest.cs b/Tests/Modbus.Net.Tests/ModbusTest.cs index b4b4833..96557d4 100644 --- a/Tests/Modbus.Net.Tests/ModbusTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusTest.cs @@ -11,10 +11,18 @@ namespace Modbus.Net.Tests { private BaseMachine _modbusTcpMachine; + private BaseMachine _modbusRtuMachine; + + private BaseMachine _modbusAsciiMachine; + [TestInitialize] public void Init() { _modbusTcpMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.10", null, true, 2, 0); + + _modbusRtuMachine = new ModbusMachine(ModbusType.Rtu, "COM3", null, true, 2, 0); + + _modbusAsciiMachine = new ModbusMachine(ModbusType.Ascii, "COM5", null, true, 2, 0); } [TestMethod] @@ -43,9 +51,17 @@ namespace Modbus.Net.Tests }; _modbusTcpMachine.GetAddresses = addresses; + _modbusAsciiMachine.GetAddresses = addresses; + _modbusRtuMachine.GetAddresses = addresses; await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + await _modbusAsciiMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + await _modbusRtuMachine.SetDatasAsync(MachineSetDataType.Address, dic1); var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.Address); + var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineGetDataType.Address); + var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineGetDataType.Address); Assert.AreEqual(ans["0X 1.0"].PlcValue, dic1["0X 1.0"]); + Assert.AreEqual(ans2["0X 1.0"].PlcValue, dic1["0X 1.0"]); + Assert.AreEqual(ans3["0X 1.0"].PlcValue, dic1["0X 1.0"]); } [TestMethod] @@ -65,8 +81,14 @@ namespace Modbus.Net.Tests }; _modbusTcpMachine.GetAddresses = addresses; + _modbusRtuMachine.GetAddresses = addresses; + _modbusAsciiMachine.GetAddresses = addresses; var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.Address); + var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineGetDataType.Address); + var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineGetDataType.Address); Assert.AreEqual(ans["1X 1.0"].PlcValue, 0); + Assert.AreEqual(ans2["1X 1.0"].PlcValue, 0); + Assert.AreEqual(ans3["1X 1.0"].PlcValue, 0); } [TestMethod] @@ -86,8 +108,14 @@ namespace Modbus.Net.Tests }; _modbusTcpMachine.GetAddresses = addresses; + _modbusRtuMachine.GetAddresses = addresses; + _modbusAsciiMachine.GetAddresses = addresses; var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.Address); + var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineGetDataType.Address); + var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineGetDataType.Address); Assert.AreEqual(ans["3X 1.0"].PlcValue, 0); + Assert.AreEqual(ans2["3X 1.0"].PlcValue, 0); + Assert.AreEqual(ans3["3X 1.0"].PlcValue, 0); } [TestMethod] @@ -116,9 +144,17 @@ namespace Modbus.Net.Tests }; _modbusTcpMachine.GetAddresses = addresses; + _modbusAsciiMachine.GetAddresses = addresses; + _modbusRtuMachine.GetAddresses = addresses; await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + await _modbusAsciiMachine.SetDatasAsync(MachineSetDataType.Address, dic1); + await _modbusRtuMachine.SetDatasAsync(MachineSetDataType.Address, dic1); var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.Address); + var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineGetDataType.Address); + var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineGetDataType.Address); Assert.AreEqual(ans["4X 1.0"].PlcValue, dic1["4X 1"]); + Assert.AreEqual(ans2["4X 1.0"].PlcValue, dic1["4X 1"]); + Assert.AreEqual(ans3["4X 1.0"].PlcValue, dic1["4X 1"]); } [TestMethod] @@ -207,15 +243,34 @@ namespace Modbus.Net.Tests }; _modbusTcpMachine.GetAddresses = addresses; + _modbusRtuMachine.GetAddresses = addresses; + _modbusAsciiMachine.GetAddresses = addresses; await _modbusTcpMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, dic1); + await _modbusRtuMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, dic1); + await _modbusAsciiMachine.SetDatasAsync(MachineSetDataType.CommunicationTag, dic1); var ans = await _modbusTcpMachine.GetDatasAsync(MachineGetDataType.CommunicationTag); + var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineGetDataType.CommunicationTag); + var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineGetDataType.CommunicationTag); + Assert.AreEqual(ans["A1"].PlcValue, dic1["A1"]); Assert.AreEqual(ans["A2"].PlcValue, dic1["A2"]); Assert.AreEqual(ans["A3"].PlcValue, dic1["A3"]); Assert.AreEqual(ans["A4"].PlcValue, dic1["A4"]); Assert.AreEqual(ans["A5"].PlcValue, dic1["A5"]); Assert.AreEqual(ans["A6"].PlcValue, dic1["A6"]); + Assert.AreEqual(ans2["A1"].PlcValue, dic1["A1"]); + Assert.AreEqual(ans2["A2"].PlcValue, dic1["A2"]); + Assert.AreEqual(ans2["A3"].PlcValue, dic1["A3"]); + Assert.AreEqual(ans2["A4"].PlcValue, dic1["A4"]); + Assert.AreEqual(ans2["A5"].PlcValue, dic1["A5"]); + Assert.AreEqual(ans2["A6"].PlcValue, dic1["A6"]); + Assert.AreEqual(ans3["A1"].PlcValue, dic1["A1"]); + Assert.AreEqual(ans3["A2"].PlcValue, dic1["A2"]); + Assert.AreEqual(ans3["A3"].PlcValue, dic1["A3"]); + Assert.AreEqual(ans3["A4"].PlcValue, dic1["A4"]); + Assert.AreEqual(ans3["A5"].PlcValue, dic1["A5"]); + Assert.AreEqual(ans3["A6"].PlcValue, dic1["A6"]); } } } From c2f3626f73c220031b9ba1d185046ca904bb0d6a Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 11:44:09 +0800 Subject: [PATCH 39/62] Temp Remove appsettings.json --- Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs index 09dd844..4b30e6b 100644 --- a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs +++ b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs @@ -13,7 +13,6 @@ namespace Modbus.Net /// private static readonly IConfigurationBuilder Builder = new ConfigurationBuilder() .SetBasePath(RootPath ?? Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json") .AddXmlFile("App.config"); /// From d7d74ee0a1341382579b78ede72587ef079bcdfb Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 12:58:03 +0800 Subject: [PATCH 40/62] Add taskmanager test --- Tests/Modbus.Net.Tests/BaseTest.cs | 6 + Tests/Modbus.Net.Tests/MachineMethodTest.cs | 3 + .../Modbus.Net.Tests/Modbus.Net.Tests.csproj | 1 + Tests/Modbus.Net.Tests/ModbusTest.cs | 8 + Tests/Modbus.Net.Tests/OpcTest.cs | 6 + Tests/Modbus.Net.Tests/SiemensTest.cs | 6 + Tests/Modbus.Net.Tests/TaskManagerTest.cs | 161 ++++++++++++++++++ 7 files changed, 191 insertions(+) create mode 100644 Tests/Modbus.Net.Tests/TaskManagerTest.cs diff --git a/Tests/Modbus.Net.Tests/BaseTest.cs b/Tests/Modbus.Net.Tests/BaseTest.cs index 9a17f52..8809a9e 100644 --- a/Tests/Modbus.Net.Tests/BaseTest.cs +++ b/Tests/Modbus.Net.Tests/BaseTest.cs @@ -326,5 +326,11 @@ namespace Modbus.Net.Tests Assert.AreEqual(addressUnit.Area, "3X"); Assert.AreEqual(addressUnit.Address, 1); } + + [TestCleanup] + public void MachineClean() + { + _baseMachine2.Disconnect(); + } } } diff --git a/Tests/Modbus.Net.Tests/MachineMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs index 29dcea8..9ff7dc4 100644 --- a/Tests/Modbus.Net.Tests/MachineMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -19,6 +19,7 @@ namespace Modbus.Net.Tests var methods = utility.GetType().GetRuntimeMethods(); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetTimeAsync") != null, true); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetTimeAsync") != null, true); + baseMachine.Disconnect(); } [TestMethod] @@ -29,6 +30,7 @@ namespace Modbus.Net.Tests Assert.AreEqual(success, true); var time = await baseMachine.BaseUtility.InvokeUtilityMethod>("GetTimeAsync"); Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true); + baseMachine.Disconnect(); } [TestMethod] @@ -66,6 +68,7 @@ namespace Modbus.Net.Tests } }); Assert.AreEqual(success, true); + baseMachine.Disconnect(); } } } diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index 454edec..2942bdd 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -59,6 +59,7 @@ + diff --git a/Tests/Modbus.Net.Tests/ModbusTest.cs b/Tests/Modbus.Net.Tests/ModbusTest.cs index 96557d4..c957dde 100644 --- a/Tests/Modbus.Net.Tests/ModbusTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusTest.cs @@ -272,5 +272,13 @@ namespace Modbus.Net.Tests Assert.AreEqual(ans3["A5"].PlcValue, dic1["A5"]); Assert.AreEqual(ans3["A6"].PlcValue, dic1["A6"]); } + + [TestCleanup] + public void MachineClean() + { + _modbusAsciiMachine.Disconnect(); + _modbusRtuMachine.Disconnect(); + _modbusTcpMachine.Disconnect(); + } } } diff --git a/Tests/Modbus.Net.Tests/OpcTest.cs b/Tests/Modbus.Net.Tests/OpcTest.cs index d60c345..95608d1 100644 --- a/Tests/Modbus.Net.Tests/OpcTest.cs +++ b/Tests/Modbus.Net.Tests/OpcTest.cs @@ -96,5 +96,11 @@ namespace Modbus.Net.Tests var ans = await _opcMachine.GetDatasAsync(MachineGetDataType.Id); Assert.AreEqual(ans["1"].PlcValue, 525); } + + [TestCleanup] + public void MachineClean() + { + _opcMachine.Disconnect(); + } } } diff --git a/Tests/Modbus.Net.Tests/SiemensTest.cs b/Tests/Modbus.Net.Tests/SiemensTest.cs index 6d4b9af..b733dd0 100644 --- a/Tests/Modbus.Net.Tests/SiemensTest.cs +++ b/Tests/Modbus.Net.Tests/SiemensTest.cs @@ -263,5 +263,11 @@ namespace Modbus.Net.Tests Assert.AreEqual(ans["A5"].PlcValue, dic1["A5"]); Assert.AreEqual(ans["A6"].PlcValue, dic1["A6"]); } + + [TestCleanup] + public void MachineClean() + { + _siemensTcpMachine.Disconnect(); + } } } diff --git a/Tests/Modbus.Net.Tests/TaskManagerTest.cs b/Tests/Modbus.Net.Tests/TaskManagerTest.cs new file mode 100644 index 0000000..fe65059 --- /dev/null +++ b/Tests/Modbus.Net.Tests/TaskManagerTest.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Modbus.Net.Modbus; + +namespace Modbus.Net.Tests +{ + [TestClass] + public class TaskManagerTest + { + private TaskManager _taskManager; + + private Dictionary _valueDic = new Dictionary(); + + private Timer _timer; + + [TestInitialize] + public void TaskManagerInit() + { + _taskManager = new TaskManager(20, true); + + var addresses = new List + { + new AddressUnit + { + Id = "0", + Area = "4X", + Address = 2, + SubAddress = 0, + CommunicationTag = "A1", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "1", + Area = "4X", + Address = 3, + SubAddress = 0, + CommunicationTag = "A2", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "2", + Area = "4X", + Address = 4, + SubAddress = 0, + CommunicationTag = "A3", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "3", + Area = "4X", + Address = 5, + SubAddress = 0, + CommunicationTag = "A4", + DataType = typeof(ushort) + }, + new AddressUnit + { + Id = "4", + Area = "4X", + Address = 6, + SubAddress = 0, + CommunicationTag = "A5", + DataType = typeof(uint) + }, + new AddressUnit + { + Id = "5", + Area = "4X", + Address = 8, + SubAddress = 0, + CommunicationTag = "A6", + DataType = typeof(uint) + } + }; + + BaseMachine machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.10", addresses, true, 2, 0); + + _taskManager.AddMachine(machine); + + var r = new Random(); + + _timer = new Timer(state => + { + lock (_valueDic) + { + _valueDic = new Dictionary + { + { + "A1", r.Next(0, UInt16.MaxValue) + }, + { + "A2", r.Next(0, UInt16.MaxValue) + }, + { + "A3", r.Next(0, UInt16.MaxValue) + }, + { + "A4", r.Next(0, UInt16.MaxValue) + }, + { + "A5", r.Next() + }, + { + "A6", r.Next() + } + }; + } + }, null, 0, 1000); + + _taskManager.InvokeTimerAll(new TaskItemSetData(_valueDic, MachineSetDataType.CommunicationTag) + { + TimerTime = 2000, + TimeoutTime = 60000, + TimerDisconnectedTime = 10000 + }); + } + + [TestMethod] + public void TaskManagerValueReadWriteTest() + { + var dicans = new Dictionary(); + _taskManager.InvokeTimerAll(new TaskItemGetData( + def => + { + dicans = def.ReturnValues.ToDictionary(p => p.Key, p => p.Value.PlcValue); + }, MachineGetDataType.CommunicationTag, 2000, 10000, 60000)); + + var i = 5; + while (i > 0) + { + Thread.Sleep(10000); + lock (dicans) + { + lock (_valueDic) + { + Assert.AreEqual(dicans["A1"], _valueDic["A1"]); + Assert.AreEqual(dicans["A2"], _valueDic["A2"]); + Assert.AreEqual(dicans["A3"], _valueDic["A3"]); + Assert.AreEqual(dicans["A4"], _valueDic["A4"]); + Assert.AreEqual(dicans["A5"], _valueDic["A5"]); + Assert.AreEqual(dicans["A6"], _valueDic["A6"]); + } + } + i--; + } + } + + [TestCleanup] + public void TaskManagerFinilize() + { + _taskManager.StopTimerAll(); + _timer.Dispose(); + } + } +} From c2bcdeac206a399fba6a5462900fc08f4b900e8f Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 14:52:13 +0800 Subject: [PATCH 41/62] Bug Fix --- Modbus.Net/src/Base.Common/TaskManager.cs | 58 ++++++++++++++++------- Tests/Modbus.Net.Tests/TaskManagerTest.cs | 40 +++++++--------- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index b1d5d6c..49a7b5d 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -352,13 +352,9 @@ namespace Modbus.Net /// 任务是否执行成功 public async Task InvokeOnce(TaskItem task) { - if (Machine.IsConnected) - { - var ans = await task.Invoke(Machine, _tasks, task.Params, task.TimeoutTime); - task.Return?.Invoke(ans); - return true; - } - return false; + var ans = await task.Invoke(Machine, _tasks, task.Params?.Invoke(), task.TimeoutTime); + task.Return?.Invoke(ans); + return true; } } @@ -409,10 +405,8 @@ namespace Modbus.Net /// /// 返回值的处理函数 /// 返回值的键类型 - /// 循环间隔(毫秒) - /// 设备离线时的循环间隔(毫秒) /// 任务的超时时间 - public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle, int sleepCycle, int timeout = 100000) + public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int timeout = 100000) { Name = "GetDatas"; TimeoutTime = timeout; @@ -433,6 +427,19 @@ namespace Modbus.Net }; Params = null; Return = returnFunc; + } + + /// + /// 构造函数 + /// + /// 返回值的处理函数 + /// 返回值的键类型 + /// 循环间隔(毫秒) + /// 设备离线时的循环间隔(毫秒) + /// 任务的超时时间 + public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle, + int sleepCycle, int timeout = 100000) : this(returnFunc, getDataType, timeout) + { TimerDisconnectedTime = sleepCycle; TimerTime = getCycle; } @@ -450,24 +457,41 @@ namespace Modbus.Net /// 写入值的键类型 /// 返回值的处理函数 /// 任务的超时时间 - public TaskItemSetData(Dictionary values, MachineSetDataType setDataType, Action returnFunc = null, int timeout = 100000) + public TaskItemSetData(Func> values, MachineSetDataType setDataType, int timeout = 100000, Action returnFunc = null) { Name = "SetDatas"; TimeoutTime = timeout; - Invoke = Invoke = async (machine, tasks, parameters, timeoutTime) => + Invoke = async (machine, tasks, parameters, timeoutTime) => { var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); var ans = await tasks.StartNew( async () => await machine.InvokeMachineMethod>("SetDatasAsync", parameters[0], - setDataType).WithCancellation(cts.Token)).Unwrap(); + Task>("SetDatasAsync", setDataType, parameters[0] + ).WithCancellation(cts.Token)).Unwrap(); return ans; }; - Params = new object[] {values}; + Params = () => new object[] {values()}; Return = returnFunc; } + + /// + /// 构造函数 + /// + /// 写入的值 + /// 写入值的键类型 + /// 返回值的处理函数 + /// 循环间隔(毫秒) + /// 设备离线时的循环间隔(毫秒) + /// 任务的超时时间 + public TaskItemSetData(Func> values, MachineSetDataType setDataType, int getCycle, + int sleepCycle, int timeout = 100000, Action returnFunc = null) + : this(values, setDataType, timeout, returnFunc) + { + TimerDisconnectedTime = sleepCycle; + TimerTime = getCycle; + } } /// @@ -514,7 +538,7 @@ namespace Modbus.Net /// /// 任务执行的参数 /// - public object[] Params { get; set; } + public Func Params { get; set; } /// /// 返回值的处理函数 @@ -575,7 +599,7 @@ namespace Modbus.Net Timer = new Timer(async state => { if (!DetectConnected()) TimerChangeToDisconnect(); - var ans = await Invoke(GetMachine(), GetTaskFactory(), Params, TimeoutTime); + var ans = await Invoke(GetMachine(), GetTaskFactory(), Params?.Invoke(), TimeoutTime); Return?.Invoke(ans); }, null, 0, TimerTime); } diff --git a/Tests/Modbus.Net.Tests/TaskManagerTest.cs b/Tests/Modbus.Net.Tests/TaskManagerTest.cs index fe65059..9c889be 100644 --- a/Tests/Modbus.Net.Tests/TaskManagerTest.cs +++ b/Tests/Modbus.Net.Tests/TaskManagerTest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Modbus.Net.Modbus; @@ -79,13 +80,16 @@ namespace Modbus.Net.Tests } }; - BaseMachine machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.10", addresses, true, 2, 0); + BaseMachine machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.10", addresses, true, 2, 0) + { + Id = "1" + }; _taskManager.AddMachine(machine); var r = new Random(); - _timer = new Timer(state => + _timer = new Timer(async state => { lock (_valueDic) { @@ -111,43 +115,31 @@ namespace Modbus.Net.Tests } }; } - }, null, 0, 1000); - - _taskManager.InvokeTimerAll(new TaskItemSetData(_valueDic, MachineSetDataType.CommunicationTag) - { - TimerTime = 2000, - TimeoutTime = 60000, - TimerDisconnectedTime = 10000 - }); + await _taskManager.InvokeOnceAll(new TaskItemSetData(() => _valueDic, MachineSetDataType.CommunicationTag)); + }, null, 0, 5000); } [TestMethod] - public void TaskManagerValueReadWriteTest() + public async Task TaskManagerValueReadWriteTest() { - var dicans = new Dictionary(); - _taskManager.InvokeTimerAll(new TaskItemGetData( - def => - { - dicans = def.ReturnValues.ToDictionary(p => p.Key, p => p.Value.PlcValue); - }, MachineGetDataType.CommunicationTag, 2000, 10000, 60000)); + Thread.Sleep(2000); var i = 5; while (i > 0) { - Thread.Sleep(10000); - lock (dicans) - { - lock (_valueDic) + Thread.Sleep(5000); + await _taskManager.InvokeOnceAll(new TaskItemGetData( + def => { + var dicans = def.ReturnValues.ToDictionary(p => p.Key, p => p.Value.PlcValue); Assert.AreEqual(dicans["A1"], _valueDic["A1"]); Assert.AreEqual(dicans["A2"], _valueDic["A2"]); Assert.AreEqual(dicans["A3"], _valueDic["A3"]); Assert.AreEqual(dicans["A4"], _valueDic["A4"]); Assert.AreEqual(dicans["A5"], _valueDic["A5"]); Assert.AreEqual(dicans["A6"], _valueDic["A6"]); - } - } - i--; + }, MachineGetDataType.CommunicationTag)); + i--; } } From 81b15eb132cca8bab7a5fbc8f6fab116b3bd4467 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 15:52:14 +0800 Subject: [PATCH 42/62] 2017-05-24 Update 2 Change verbose text. --- .../Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs | 4 +++- Modbus.Net/Modbus.Net/ComConnector.cs | 16 +++++++++------- Modbus.Net/src/Base.Common/TcpConnector.cs | 18 +++++++++--------- Tests/Modbus.Net.Tests/App.config | 6 ------ Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj | 3 --- 5 files changed, 21 insertions(+), 26 deletions(-) delete mode 100644 Tests/Modbus.Net.Tests/App.config diff --git a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs index 997c627..c1f4827 100644 --- a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs +++ b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs @@ -17,7 +17,9 @@ namespace Modbus.Net.OPC.FBox /// 是否保持连接 public FBoxOpcDaMachine(string localSequence, string linkerName, IEnumerable getAddresses, bool keepConnect) - : base(ConfigurationManager.AppSettings["FBoxOpcDaHost"], getAddresses, keepConnect) + : base( + ConfigurationManager.AppSettings["FBoxOpcDaHost"] ?? "opcda://localhost/FBoxOpcServer", getAddresses, + keepConnect) { LocalSequence = localSequence; LinkerName = linkerName; diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs index 71ab2d2..0c5b417 100644 --- a/Modbus.Net/Modbus.Net/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/ComConnector.cs @@ -312,19 +312,19 @@ namespace Modbus.Net private void RefreshSendCount() { _sendCount++; - Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); + Log.Verbose("Com client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount); } private void RefreshReceiveCount() { _receiveCount++; - Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + Log.Verbose("Com client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); } private void RefreshErrorCount() { _errorCount++; - Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + Log.Verbose("Com client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); } #region 发送接收数据 @@ -458,7 +458,8 @@ namespace Modbus.Net { Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); - Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); + Log.Verbose( + $"Com client {ConnectionToken} send msg: {String.Concat(sendbytes.Select(p => " " + p))}"); SerialPort.Write(sendbytes, 0, sendbytes.Length); } catch (Exception err) @@ -473,8 +474,8 @@ namespace Modbus.Net returnBytes = ReadMsg(); Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, returnBytes.Length); - Log.Verbose("Com client {ConnectionToken} receive msg: {SendBytes}", ConnectionToken, - returnBytes); + Log.Verbose( + $"Com client {ConnectionToken} receive msg: {String.Concat(returnBytes.Select(p => " " + p))}"); } catch (Exception e) { @@ -529,7 +530,8 @@ namespace Modbus.Net { Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); - Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); + Log.Verbose( + $"Com client {ConnectionToken} send msg: {string.Concat(sendbytes.Select(p => " " + p))}"); SerialPort.Write(sendbytes, 0, sendbytes.Length); } catch (Exception err) diff --git a/Modbus.Net/src/Base.Common/TcpConnector.cs b/Modbus.Net/src/Base.Common/TcpConnector.cs index 2e71893..a73c96f 100644 --- a/Modbus.Net/src/Base.Common/TcpConnector.cs +++ b/Modbus.Net/src/Base.Common/TcpConnector.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -240,7 +241,7 @@ namespace Modbus.Net var stream = _socketClient.GetStream(); Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); - Log.Verbose("Tcp client {ConnectionToken} send text = {Datagram}", ConnectionToken, datagram); + Log.Verbose($"Tcp client {ConnectionToken} send text = {String.Concat(datagram.Select(p => " " + p))}"); await stream.WriteAsync(datagram, 0, datagram.Length); RefreshSendCount(); @@ -281,16 +282,18 @@ namespace Modbus.Net var stream = _socketClient.GetStream(); - Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); - Log.Verbose("Tcp client {ConnectionToken} send: {Datagram}", ConnectionToken, datagram); - await stream.WriteAsync(datagram, 0, datagram.Length); - RefreshSendCount(); + Log.Verbose("Tcp client {ConnectionToken} send text len = {Length}", ConnectionToken, datagram.Length); + Log.Verbose($"Tcp client {ConnectionToken} send: {String.Concat(datagram.Select(p => " " + p))}"); + await stream.WriteAsync(datagram, 0, datagram.Length); + var receiveBytes = await ReceiveAsync(stream); Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, receiveBytes.Length); - Log.Verbose("Tcp client {ConnectionToken} receive: {Datagram}", ConnectionToken, receiveBytes); + Log.Verbose($"Tcp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p))}"); + + RefreshReceiveCount(); return receiveBytes; } @@ -335,9 +338,6 @@ namespace Modbus.Net var replyMessage = new byte[len]; Array.Copy(_receiveBuffer, replyMessage, len); - Log.Verbose("Tcp client {ConnectionToken} reply: {replyMessage}", ConnectionToken, replyMessage); - RefreshReceiveCount(); - if (len <= 0) RefreshErrorCount(); diff --git a/Tests/Modbus.Net.Tests/App.config b/Tests/Modbus.Net.Tests/App.config deleted file mode 100644 index 7802c78..0000000 --- a/Tests/Modbus.Net.Tests/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index 2942bdd..82f82f2 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -79,9 +79,6 @@ Modbus.Net - - - From c45b779b48ff00f7a8c248236a0fca515b226954 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 24 May 2017 16:48:44 +0800 Subject: [PATCH 43/62] Fix a bug in LRC --- Modbus.Net/src/Base.Common/CRC16.cs | 2 ++ .../Modbus.Net.Tests/Modbus.Net.Tests.csproj | 5 +++ Tests/Modbus.Net.Tests/Modbus.Net.orderedtest | 33 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 Tests/Modbus.Net.Tests/Modbus.Net.orderedtest diff --git a/Modbus.Net/src/Base.Common/CRC16.cs b/Modbus.Net/src/Base.Common/CRC16.cs index 478d6e2..16e19b2 100644 --- a/Modbus.Net/src/Base.Common/CRC16.cs +++ b/Modbus.Net/src/Base.Common/CRC16.cs @@ -176,6 +176,8 @@ namespace Modbus.Net } hexTotal = string.Concat(hexByte, hexTotal); } + if (hexTotal.Length == 0) hexTotal = "00" + hexTotal; + if (hexTotal.Length == 1) hexTotal = "0" + hexTotal; return hexTotal == checkString; } diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index 82f82f2..0d888dc 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -79,6 +79,11 @@ Modbus.Net + + + PreserveNewest + + diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.orderedtest b/Tests/Modbus.Net.Tests/Modbus.Net.orderedtest new file mode 100644 index 0000000..cb74ea2 --- /dev/null +++ b/Tests/Modbus.Net.Tests/Modbus.Net.orderedtest @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 72fd21fd666ed562e7bfaace4e2ed6445a974711 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 25 May 2017 10:12:45 +0800 Subject: [PATCH 44/62] Overview Update --- README.md | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 1cf4274..00539f8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Modbus.Net Oveview =================== * [Teambition Project](https://www.teambition.com/project/573860b0f668c69e61d38a84/tasks) +* QQȺ 438411519 Modbus.NetȺ Overview ------------------- @@ -58,33 +59,46 @@ Platform Supported * Generic Method For ProtocalUnit (Complete) ### Version 1.3.2 -* Add Interface IMachineMethod and IUtilityMethod. Utiltiy and Machine can extend function using interface (Not Tested) +* Add Interface IMachineMethod and IUtilityMethod. Utiltiy and Machine can extend function using interface (Complete) ### Version 1.3.3 -* TaskManager Remake (Not Tested) +* TaskManager Remake (Complete) ### Version 1.3.4 -* A Serial Port now can connect to multiple machines using same protocol with different slave address (Not Tested) +* A Serial Port now can connect to multiple machines using same protocol with different slave address (Complete) ### Version 1.3.5 -* New log system using serilog (Not Tested) +* New log system using serilog (Complete) ### Version 1.3.6 -* Add gereric Type for BaseConnector, now protocol developer can pass any type to BaseConnector not only byte[] (Not Tested) -* Add more gereric types in Modbus.Net to support this function (Not Tested) -* Add more interfaces to make them completed in Modbus.Net (Not Tested) -* Support this function in Modbus.Net.OPC (Not Tested) +* Add gereric Type for BaseConnector, now protocol developer can pass any type to BaseConnector not only byte[] (Complete) +* Add more gereric types in Modbus.Net to support this function (Complete) +* Add more interfaces to make them completed in Modbus.Net (Complete) +* Support this function in Modbus.Net.OPC (Complete) ### Version 1.3.7 -* AddressCombiner need to add maximum length now. Combiner will consider the maximum length when combining addresses (Not Tested) +* AddressCombiner need to add maximum length now. Combiner will consider the maximum length when combining addresses (Complete) ### 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 +* Change Resx to app.config or appsettings.json, now you can set default params there (Complete) +* Change ISpecialProtocalUnit to SpecialProtocalUnitAttribute (Complete) + +### Version 1.3.9 +* Modbus Single Write for Coil and Reg (05 and 06) (In Road) + +* Github wiki Document Chinese (Not Complete) +* Github wiki Document English (In Road) ### Version 1.4.0 -* New Protocal Pipeline System (In Road) +* BaseController (In Road) * New ComConnector (In Road) -* Multi station Modbus RTU, ASCII and Siemens PPI (In Road) +* Serial Port Connection with Multiple Master Station (In Road) + +### Version 1.4.1 +* New Protocal Pipeline System (In Road) +* PPI Remake (In Road) + +### Version 1.4.2 * Siemens MPI Support (In Road) -* Github wiki Document (In Road) +* Siemens MultiStation PPI Support (In Road) + From 405541ef3b91d0caeb5791574783a806b9132ec1 Mon Sep 17 00:00:00 2001 From: "Chris L.(Luo Sheng)" Date: Thu, 25 May 2017 10:15:04 +0800 Subject: [PATCH 45/62] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00539f8..2ef848f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Modbus.Net Oveview =================== * [Teambition Project](https://www.teambition.com/project/573860b0f668c69e61d38a84/tasks) -* QQȺ 438411519 Modbus.NetȺ +* QQ群 438411519 Modbus.Net交流群 Overview ------------------- From d9b05ec42e1edb7f8ee2b42b0036d1cb82bfc13d Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 25 May 2017 10:16:33 +0800 Subject: [PATCH 46/62] Update License.md --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index da42ba7..1b30028 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,5 +1,5 @@ ### The MIT License (MIT) -Copyright © 2015 Hangzhou Delian IoT Science Technology Co.,Ltd. +Copyright © 2017 Hangzhou Delian IoT Science Technology Co.,Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From 3cbaf44cbeb2acbb890dac2bb92bd98969cd5cd4 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 25 May 2017 10:23:19 +0800 Subject: [PATCH 47/62] Change Coding --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ef848f..ba82ab5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Modbus.Net Oveview +Modbus.Net Oveview =================== * [Teambition Project](https://www.teambition.com/project/573860b0f668c69e61d38a84/tasks) From 96c12d5806f0a8a71965d2a23c49bdc0937d4cf8 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 25 May 2017 10:40:56 +0800 Subject: [PATCH 48/62] Fix Doc --- LICENSE.md => LICENSE | 0 Modbus.Net/Modbus.Net.sln | 3 +-- README.md | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) rename LICENSE.md => LICENSE (100%) diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln index f213f2a..945766a 100644 --- a/Modbus.Net/Modbus.Net.sln +++ b/Modbus.Net/Modbus.Net.sln @@ -1,13 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26403.0 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net", "Modbus.Net\Modbus.Net.csproj", "{124EBEF2-8960-4447-84CF-1D683B1EF7CC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{64472271-8B95-4036-ACF9-C10941C1DB0A}" ProjectSection(SolutionItems) = preProject - ..\LICENSE.md = ..\LICENSE.md ..\README.md = ..\README.md EndProjectSection EndProject diff --git a/README.md b/README.md index ba82ab5..427dacd 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Platform Supported ### Version 1.3.9 * Modbus Single Write for Coil and Reg (05 and 06) (In Road) +### * Github wiki Document Chinese (Not Complete) * Github wiki Document English (In Road) From 9281ed9f310e10184989a98797baa6848afc29f7 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 25 May 2017 10:46:22 +0800 Subject: [PATCH 49/62] Fix --- LICENSE | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/LICENSE b/LICENSE index 1b30028..e994267 100644 --- a/LICENSE +++ b/LICENSE @@ -1,8 +1,21 @@ -### The MIT License (MIT) -Copyright © 2017 Hangzhou Delian IoT Science Technology Co.,Ltd. +MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) 2017 Hangzhou Delian IoT Science Technology Co.,Ltd. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 9d5f125810deef15137b176ce8d540924464cf73 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Sat, 27 May 2017 16:51:16 +0800 Subject: [PATCH 50/62] Change app.config to appsettings.json --- Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs | 2 +- Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs index 4b30e6b..4891ce1 100644 --- a/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs +++ b/Modbus.Net/Modbus.Net.Core/ConfigurationManager.cs @@ -13,7 +13,7 @@ namespace Modbus.Net /// private static readonly IConfigurationBuilder Builder = new ConfigurationBuilder() .SetBasePath(RootPath ?? Directory.GetCurrentDirectory()) - .AddXmlFile("App.config"); + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); /// /// RootPath of App.config and appsettings.json diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 1752996..cbfd3ff 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.8-beta1 + 1.3.8-beta2 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -54,7 +54,7 @@ - + From 79ddc0394f0a60084830006b292ef64a89750b20 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Sat, 27 May 2017 16:54:04 +0800 Subject: [PATCH 51/62] Fix --- Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index cbfd3ff..7fbf452 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -54,7 +54,6 @@ - From 5b52c5c4157f7f2409cc576dd9b1d7819f273222 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 31 May 2017 11:01:13 +0800 Subject: [PATCH 52/62] Change App.Config sample to appsettings.json sample --- Modbus.Net/Modbus.Net.Core/App.config | 14 -------------- Modbus.Net/Modbus.Net.Core/appsettings.json | 10 ++++++++++ 2 files changed, 10 insertions(+), 14 deletions(-) delete mode 100644 Modbus.Net/Modbus.Net.Core/App.config create mode 100644 Modbus.Net/Modbus.Net.Core/appsettings.json diff --git a/Modbus.Net/Modbus.Net.Core/App.config b/Modbus.Net/Modbus.Net.Core/App.config deleted file mode 100644 index 8874465..0000000 --- a/Modbus.Net/Modbus.Net.Core/App.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Core/appsettings.json b/Modbus.Net/Modbus.Net.Core/appsettings.json new file mode 100644 index 0000000..12febb4 --- /dev/null +++ b/Modbus.Net/Modbus.Net.Core/appsettings.json @@ -0,0 +1,10 @@ +{ + "AppSettings": { + "COM": "COM1", + "IP": "192.168.1.1", + "ComConnectionTimeout": "3000", + "IPConnectionTimeout": "5000", + "ModbusPort": "502", + "SiemensPort": "102" + } +} \ No newline at end of file From 8a46643a094e30ca87697f77358601c72828d836 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 1 Jun 2017 18:27:59 +0800 Subject: [PATCH 53/62] Assembly Name Fix. --- Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 7fbf452..37eba7e 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -2,7 +2,7 @@ netstandard1.3 - Modbus.Net + Modbus.Net.Core Modbus.Net Modbus.Net.Core 1.3.8-beta2 From 6e01f0c1e6239d440e5f1700c4196441771acf64 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 1 Jun 2017 18:37:13 +0800 Subject: [PATCH 54/62] Add IConnector --- .../Modbus.Net.Core/Modbus.Net.Core.csproj | 3 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 3 +- Modbus.Net/src/Base.Common/BaseConnector.cs | 2 +- Modbus.Net/src/Base.Common/IConnector.cs | 66 +++++++++++++++++++ Modbus.Net/src/Base.Common/ProtocalLinker.cs | 2 +- 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 Modbus.Net/src/Base.Common/IConnector.cs diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 37eba7e..eec5ef8 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.Core Modbus.Net Modbus.Net.Core - 1.3.8-beta2 + 1.3.8-beta3 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -49,6 +49,7 @@ + diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index ffd5b50..e24f0ac 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.8-beta1 + 1.3.8-beta2 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -48,6 +48,7 @@ + diff --git a/Modbus.Net/src/Base.Common/BaseConnector.cs b/Modbus.Net/src/Base.Common/BaseConnector.cs index 1232ac8..1b2df7b 100644 --- a/Modbus.Net/src/Base.Common/BaseConnector.cs +++ b/Modbus.Net/src/Base.Common/BaseConnector.cs @@ -12,7 +12,7 @@ namespace Modbus.Net /// /// 基础的协议连接类 /// - public abstract class BaseConnector + public abstract class BaseConnector : IConnector { /// /// 标识Connector的连接关键字 diff --git a/Modbus.Net/src/Base.Common/IConnector.cs b/Modbus.Net/src/Base.Common/IConnector.cs new file mode 100644 index 0000000..0a73e86 --- /dev/null +++ b/Modbus.Net/src/Base.Common/IConnector.cs @@ -0,0 +1,66 @@ +using System.Threading.Tasks; + +namespace Modbus.Net +{ + /// + /// Эӽӿ + /// + public interface IConnector + { + /// + /// ʶConnectorӹؼ + /// + string ConnectionToken { get; } + + /// + /// Ƿ״̬ + /// + bool IsConnected { get; } + + /// + /// PLC + /// + /// Ƿӳɹ + bool Connect(); + + /// + /// PLC첽 + /// + /// Ƿӳɹ + Task ConnectAsync(); + + /// + /// ϿPLC + /// + /// ǷϿɹ + bool Disconnect(); + + /// + /// ޷ط + /// + /// Ҫ͵ + /// Ƿͳɹ + bool SendMsgWithoutReturn(TParamIn message); + + /// + /// ޷ط + /// + /// Ҫ͵ + /// Ƿͳɹ + Task SendMsgWithoutReturnAsync(TParamIn message); + + /// + /// ط + /// + /// Ҫ͵ + /// Ƿͳɹ + TParamOut SendMsg(TParamIn message); + + /// + /// ط + /// + /// Ҫ͵ + /// Ƿͳɹ + Task SendMsgAsync(TParamIn message); + } +} \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index 9c9716c..8381e18 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -76,7 +76,7 @@ namespace Modbus.Net /// /// 传输连接器 /// - protected BaseConnector BaseConnector; + protected IConnector BaseConnector; /// /// 连接设备 From d85aee17eeccce58c3a11c9ee0e62045816b5da1 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 14 Jun 2017 12:17:40 +0800 Subject: [PATCH 55/62] 2017-06-14 update 1 add modbus single write and change invoke method to get methods. --- .../Modbus.Net.Core/Modbus.Net.Core.csproj | 3 + .../AddressTranslatorModbus.cs | 125 ++++++++++++++--- .../Modbus.Net.Modbus.csproj | 3 + .../Modbus.Net.Modbus/ModbusProtocal.cs | 132 ++++++++++++++++++ Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs | 37 ++++- .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 3 + .../Modbus.Net.Siemens.csproj | 3 + Modbus.Net/Modbus.Net/Modbus.Net.csproj | 4 + Modbus.Net/src/Base.Common/BaseMachine.cs | 36 ++--- Modbus.Net/src/Base.Common/BaseUtility.cs | 31 ++-- Modbus.Net/src/Base.Common/TaskManager.cs | 8 +- Tests/Modbus.Net.Tests/MachineMethodTest.cs | 10 +- 12 files changed, 320 insertions(+), 75 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index eec5ef8..c473162 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -18,6 +18,8 @@ git False True + True + True @@ -59,6 +61,7 @@ + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs index b4b6ec4..05ca20d 100644 --- a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs +++ b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs @@ -3,10 +3,33 @@ using System.Linq; namespace Modbus.Net.Modbus { + public abstract class ModbusTranslatorBase : AddressTranslator + { + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 是否只写入一个数据 + /// 翻译后的地址 + public abstract AddressDef AddressTranslate(string address, bool isRead, bool isSingle); + + /// + /// 地址转换 + /// + /// 格式化的地址 + /// 是否为读取,是为读取,否为写入 + /// 翻译后的地址 + public override AddressDef AddressTranslate(string address, bool isRead) + { + return AddressTranslate(address, isRead, false); + } + } + /// /// 南大奥拓NA200H数据单元翻译器 /// - public class AddressTranslatorNA200H : AddressTranslator + public class AddressTranslatorNA200H : ModbusTranslatorBase { /// /// 读功能码 @@ -21,7 +44,7 @@ namespace Modbus.Net.Modbus /// /// 写功能码 /// - protected Dictionary WriteFunctionCodeDictionary; + protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary; /// /// 构造器 @@ -104,10 +127,10 @@ namespace Modbus.Net.Modbus new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2} } }; - WriteFunctionCodeDictionary = new Dictionary + WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef> { { - "Q", + ("Q", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, @@ -115,7 +138,7 @@ namespace Modbus.Net.Modbus } }, { - "M", + ("M", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, @@ -123,7 +146,7 @@ namespace Modbus.Net.Modbus } }, { - "N", + ("N", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, @@ -131,7 +154,7 @@ namespace Modbus.Net.Modbus } }, { - "MW", + ("MW", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, @@ -139,7 +162,7 @@ namespace Modbus.Net.Modbus } }, { - "NW", + ("NW", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, @@ -147,12 +170,60 @@ namespace Modbus.Net.Modbus } }, { - "QW", + ("QW", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2 } + }, + { + ("Q", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil, + AreaWidth = 0.125 + } + }, + { + ("M", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil, + AreaWidth = 0.125 + } + }, + { + ("N", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil, + AreaWidth = 0.125 + } + }, + { + ("MW", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister, + AreaWidth = 2 + } + }, + { + ("NW", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister, + AreaWidth = 2 + } + }, + { + ("QW", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister, + AreaWidth = 2 + } } }; } @@ -162,8 +233,9 @@ namespace Modbus.Net.Modbus /// /// 格式化的地址 /// 是否为读取,是为读取,否为写入 + /// 是否只写入一个数据 /// 翻译后的地址 - public override AddressDef AddressTranslate(string address, bool isRead) + public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle) { address = address.ToUpper(); var splitString = address.Split(' '); @@ -191,7 +263,7 @@ namespace Modbus.Net.Modbus : new AddressDef { AreaString = head, - Area = WriteFunctionCodeDictionary[head].Code, + Area = WriteFunctionCodeDictionary[(head, isSingle)].Code, Address = TransDictionary[head] + int.Parse(tail) - 1, SubAddress = int.Parse(sub) }; @@ -211,7 +283,7 @@ namespace Modbus.Net.Modbus /// /// Modbus数据单元翻译器 /// - public class AddressTranslatorModbus : AddressTranslator + public class AddressTranslatorModbus : ModbusTranslatorBase { /// /// 读功能码 @@ -221,7 +293,7 @@ namespace Modbus.Net.Modbus /// /// 写功能码 /// - protected Dictionary WriteFunctionCodeDictionary; + protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary; /// /// 构造器 @@ -255,10 +327,10 @@ namespace Modbus.Net.Modbus new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2} } }; - WriteFunctionCodeDictionary = new Dictionary + WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef> { { - "0X", + ("0X", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, @@ -266,12 +338,28 @@ namespace Modbus.Net.Modbus } }, { - "4X", + ("4X", false), new AreaOutputDef { Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2 } + }, + { + ("0X", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil, + AreaWidth = 0.125 + } + }, + { + ("4X", true), + new AreaOutputDef + { + Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister, + AreaWidth = 2 + } } }; } @@ -281,8 +369,9 @@ namespace Modbus.Net.Modbus /// /// 格式化的地址 /// 是否为读取,是为读取,否为写入 + /// 是否只写入一个数据 /// 翻译后的地址 - public override AddressDef AddressTranslate(string address, bool isRead) + public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle) { address = address.ToUpper(); var splitString = address.Split(' '); @@ -310,7 +399,7 @@ namespace Modbus.Net.Modbus : new AddressDef { AreaString = head, - Area = WriteFunctionCodeDictionary[head].Code, + Area = WriteFunctionCodeDictionary[(head, isSingle)].Code, Address = int.Parse(tail) - 1, SubAddress = int.Parse(sub) }; diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index 93e0701..8e9385a 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -16,7 +16,10 @@ https://github.com/parallelbgls/Modbus.Net git hardware communicate protocal modbus Delian + False True + True + True diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs index 9f2a763..ee2e3e4 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs @@ -385,6 +385,138 @@ namespace Modbus.Net.Modbus } } + /// + /// 写数据输入 + /// + public class WriteSingleDataModbusInputStruct : IInputStruct + { + /// + /// 构造函数 + /// + /// 从站号 + /// 开始地址 + /// 写入的数据 + /// 地址翻译器 + /// 端格式 + public WriteSingleDataModbusInputStruct(byte slaveAddress, string startAddress, object writeValue, + ModbusTranslatorBase addressTranslator, Endian endian) + { + SlaveAddress = slaveAddress; + var translateAddress = addressTranslator.AddressTranslate(startAddress, false, true); + FunctionCode = (byte) translateAddress.Area; + StartAddress = (ushort) translateAddress.Address; + int a = 0, b = 0; + var writeByteValue = + FunctionCode == (byte) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil + ? ((bool) writeValue + ? new byte[] {0xFF, 0x00} + : new byte[] {0x00, 0xFF}) + : ValueHelper.GetInstance(endian).GetBytes(ushort.Parse(writeValue.ToString())); + WriteValue = writeByteValue; + } + + + /// + /// 从站号 + /// + public byte SlaveAddress { get; } + + /// + /// 功能码 + /// + public byte FunctionCode { get; } + + /// + /// 开始地址 + /// + public ushort StartAddress { get; } + + /// + /// 写入的数据 + /// + public byte[] WriteValue { get; } + } + + /// + /// 写数据输出 + /// + public class WriteSingleDataModbusOutputStruct : IOutputStruct + { + /// + /// 构造函数 + /// + /// 从站号 + /// 功能码 + /// 开始地址 + /// 写入的数据 + public WriteSingleDataModbusOutputStruct(byte slaveAddress, byte functionCode, + ushort startAddress, object writeValue) + { + SlaveAddress = slaveAddress; + FunctionCode = functionCode; + StartAddress = startAddress; + WriteValue = writeValue; + } + + /// + /// 从站号 + /// + public byte SlaveAddress { get; private set; } + + /// + /// 功能码 + /// + public byte FunctionCode { get; private set; } + + /// + /// 开始地址 + /// + public ushort StartAddress { get; private set; } + + /// + /// 写入的数据 + /// + public object WriteValue { get; private set; } + } + + /// + /// 写多个寄存器协议 + /// + public class WriteSingleDataModbusProtocal : ProtocalUnit + { + /// + /// 格式化 + /// + /// 写寄存器参数 + /// 写寄存器协议核心 + public override byte[] Format(IInputStruct message) + { + var r_message = (WriteSingleDataModbusInputStruct) message; + var dataValue = Format(r_message.WriteValue); + var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode, + r_message.StartAddress, dataValue); + return formattingBytes; + } + + /// + /// 反格式化 + /// + /// 设备返回的信息 + /// 当前反格式化的位置 + /// 反格式化的信息 + public override IOutputStruct Unformat(byte[] messageBytes, ref int flag) + { + var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); + var functionCode = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); + var startAddress = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag); + var writeValue = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag); + var returnValue = functionCode == (byte)ModbusProtocalWriteDataFunctionCode.WriteSingleCoil + ? (object)(writeValue == 0xFF00) : writeValue; + return new WriteSingleDataModbusOutputStruct(slaveAddress, functionCode, startAddress, + returnValue); + } + } + #endregion #region 读PLC时间 diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index 8aba0ad..7180119 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -25,10 +25,21 @@ namespace Modbus.Net.Modbus Ascii = 2 } + public interface IUtilityMethodWriteSingle : IUtilityMethod + { + /// + /// 写数据 + /// + /// 起始地址 + /// 需要设置的数据 + /// 设置是否成功 + Task SetSingleDataAsync(string startAddress, object setContent); + } + /// /// Modbus基础Api入口 /// - public class ModbusUtility : BaseUtility, IUtilityMethodTime + public class ModbusUtility : BaseUtility, IUtilityMethodTime, IUtilityMethodWriteSingle { /// /// Modbus协议类型 @@ -250,5 +261,29 @@ namespace Modbus.Net.Modbus return false; } } + + /// + /// 写数据 + /// + /// 起始地址 + /// 需要设置的数据 + /// 设置是否成功 + public async Task SetSingleDataAsync(string startAddress, object setContent) + { + try + { + var inputStruct = new WriteSingleDataModbusInputStruct(SlaveAddress, startAddress, setContent, + (ModbusTranslatorBase)AddressTranslator, Endian); + var outputStruct = await + Wrapper.SendReceiveAsync(Wrapper[typeof(WriteSingleDataModbusProtocal)], + inputStruct); + return outputStruct?.WriteValue.ToString() == setContent.ToString(); + } + catch (Exception e) + { + Log.Error(e, $"ModbusUtility -> SetSingleDatas: {ConnectionString} error"); + 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 02d839e..df1c440 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -16,7 +16,10 @@ git hardware communicate protocal OPC DA Delian False + False True + True + True diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 68e6b31..fc381ae 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -15,7 +15,10 @@ https://github.com/parallelbgls/Modbus.Net git hardware communicate protocal Siemens profinet Delian + False True + True + True diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index e24f0ac..5acf3d2 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -16,7 +16,10 @@ Copyright 2017 Hangzhou Delian IoT Science Technology Co.,Ltd. hardware communicate protocal Delian git + False True + True + True @@ -54,6 +57,7 @@ + diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index e247760..ac83417 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -243,7 +243,7 @@ namespace Modbus.Net //获取数据 var datas = await - BaseUtility.InvokeUtilityMethod>("GetDatasAsync", + BaseUtility.GetUtilityMethods().GetDatasAsync( AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, communicateAddress.SubAddress), (int) @@ -446,7 +446,7 @@ namespace Modbus.Net communicateAddress.Address); var datasReturn = - await BaseUtility.InvokeUtilityMethod>("GetDatasAsync", + await BaseUtility.GetUtilityMethods().GetDatasAsync( AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0), (int) Math.Ceiling(communicateAddress.GetCount * @@ -536,7 +536,7 @@ namespace Modbus.Net } //写入数据 await - BaseUtility.InvokeUtilityMethod>("SetDatasAsync", addressStart, + BaseUtility.GetUtilityMethods().SetDatasAsync(addressStart, valueHelper.ByteArrayToObjectArray(datas, new KeyValuePair(communicateAddress.DataType, communicateAddress.GetCount))); } @@ -591,25 +591,13 @@ namespace Modbus.Net /// public string ConnectionToken => BaseUtility.ConnectionToken; - /// - /// 调用Machine中的方法 - /// - /// Machine实现的接口名称 - /// 返回值的类型 - /// 方法的名称 - /// 方法的参数 - /// - public TReturnType InvokeMachineMethod(string methodName, - params object[] parameters) where TMachineMethod : IMachineMethod + public TMachineMethod GetMachineMethods() where TMachineMethod : class, IMachineMethod { if (this is TMachineMethod) { - var t = typeof(TMachineMethod); - var returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray()) - .Invoke(this, parameters); - return (TReturnType) returnValue; + return this as TMachineMethod; } - throw new InvalidCastException($"Machine interface {nameof(TMachineMethod)} not implemented"); + return null; } /// @@ -876,15 +864,11 @@ namespace Modbus.Net IUtilityProperty BaseUtility { get; } /// - /// 调用Machine中的方法 + /// 获取设备的方法集合 /// - /// Machine实现的接口名称 - /// 返回值的类型 - /// 方法的名称 - /// 方法的参数 - /// - TReturnType InvokeMachineMethod(string methodName, - params object[] parameters) where TMachineMethod : IMachineMethod; + /// 方法集合的类型 + /// 设备的方法集合 + TMachineMethod GetMachineMethods() where TMachineMethod : class, IMachineMethod; /// /// 连接设备 diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index fb1cd9b..f6a7797 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -277,24 +277,17 @@ namespace Modbus.Net } /// - /// 调用Utility中的方法 + /// 返回Utility的方法集合 /// - /// Utility实现的接口名称 - /// 返回值的类型 - /// 方法的名称 - /// 方法的参数 - /// - public TReturnType InvokeUtilityMethod(string methodName, - params object[] parameters) where TUtilityMethod : IUtilityMethod + /// Utility方法集合类型 + /// Utility方法集合 + public TUtilityMethod GetUtilityMethods() where TUtilityMethod : class, IUtilityMethod { if (this is TUtilityMethod) { - var t = typeof(TUtilityMethod); - var returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray(), false) - .Invoke(this, parameters); - return (TReturnType) returnValue; + return this as TUtilityMethod; } - throw new InvalidCastException($"Utility interface {nameof(TUtilityMethod)} not implemented"); + return null; } /// @@ -348,14 +341,10 @@ namespace Modbus.Net bool Disconnect(); /// - /// 调用Utility中的方法 + /// 返回Utility的方法集合 /// - /// Utility实现的接口名称 - /// 返回值的类型 - /// 方法的名称 - /// 方法的参数 - /// - TReturnType InvokeUtilityMethod(string methodName, - params object[] parameters) where TUtilityMethod : IUtilityMethod; + /// Utility方法集合类型 + /// Utility方法集合 + TUtilityMethod GetUtilityMethods() where TUtilityMethod : class, IUtilityMethod; } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 49a7b5d..3ee6be2 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -416,8 +416,8 @@ namespace Modbus.Net cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); var ans = await tasks.StartNew( - async () => await machine.InvokeMachineMethod>>("GetDatasAsync", + async () => await machine.GetMachineMethods() + .GetDatasAsync( getDataType).WithCancellation(cts.Token)).Unwrap(); return new DataReturnDef { @@ -467,8 +467,8 @@ namespace Modbus.Net cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); var ans = await tasks.StartNew( - async () => await machine.InvokeMachineMethod>("SetDatasAsync", setDataType, parameters[0] + async () => await machine.GetMachineMethods(). + SetDatasAsync(setDataType, (Dictionary)parameters[0] ).WithCancellation(cts.Token)).Unwrap(); return ans; }; diff --git a/Tests/Modbus.Net.Tests/MachineMethodTest.cs b/Tests/Modbus.Net.Tests/MachineMethodTest.cs index 9ff7dc4..8d99598 100644 --- a/Tests/Modbus.Net.Tests/MachineMethodTest.cs +++ b/Tests/Modbus.Net.Tests/MachineMethodTest.cs @@ -26,9 +26,9 @@ namespace Modbus.Net.Tests public async Task InvokeUtility() { BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); - var success = await baseMachine.BaseUtility.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); + var success = await baseMachine.BaseUtility.GetUtilityMethods().SetTimeAsync(DateTime.Now); Assert.AreEqual(success, true); - var time = await baseMachine.BaseUtility.InvokeUtilityMethod>("GetTimeAsync"); + var time = await baseMachine.BaseUtility.GetUtilityMethods().GetTimeAsync(); Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true); baseMachine.Disconnect(); } @@ -48,7 +48,7 @@ namespace Modbus.Net.Tests DataType = typeof(bool) } }, true, 2, 0); - var success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", + var success = await baseMachine.GetMachineMethods().SetDatasAsync( MachineSetDataType.Address, new Dictionary { @@ -57,9 +57,9 @@ namespace Modbus.Net.Tests } }); Assert.AreEqual(success, true); - var datas = await baseMachine.InvokeMachineMethod>>("GetDatasAsync", MachineGetDataType.Address); + var datas = await baseMachine.GetMachineMethods().GetDatasAsync(MachineGetDataType.Address); Assert.AreEqual(datas["0X 1.0"].PlcValue, 1); - success = await baseMachine.InvokeMachineMethod>("SetDatasAsync", + success = await baseMachine.GetMachineMethods().SetDatasAsync( MachineSetDataType.Address, new Dictionary { From 0096f5db25679dcb7d761c33de1757d3d113e36c Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 14 Jun 2017 17:02:38 +0800 Subject: [PATCH 56/62] Fix --- .../Modbus.Net.Modbus/ModbusProtocal.cs | 2 +- Tests/Modbus.Net.Tests/ModbusTest.cs | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs index ee2e3e4..c6c3d52 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocal.cs @@ -410,7 +410,7 @@ namespace Modbus.Net.Modbus FunctionCode == (byte) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil ? ((bool) writeValue ? new byte[] {0xFF, 0x00} - : new byte[] {0x00, 0xFF}) + : new byte[] {0x00, 0x00}) : ValueHelper.GetInstance(endian).GetBytes(ushort.Parse(writeValue.ToString())); WriteValue = writeByteValue; } diff --git a/Tests/Modbus.Net.Tests/ModbusTest.cs b/Tests/Modbus.Net.Tests/ModbusTest.cs index c957dde..0306d9b 100644 --- a/Tests/Modbus.Net.Tests/ModbusTest.cs +++ b/Tests/Modbus.Net.Tests/ModbusTest.cs @@ -273,6 +273,46 @@ namespace Modbus.Net.Tests Assert.AreEqual(ans3["A6"].PlcValue, dic1["A6"]); } + [TestMethod] + public async Task ModbusWriteSingleTest() + { + Random r = new Random(); + + var dic1 = new Dictionary() + { + { + "4X 1", r.Next(0, UInt16.MaxValue) + } + }; + + var dic2 = new Dictionary() + { + { + "0X 1", r.Next(0, 2) + } + }; + + await _modbusTcpMachine.BaseUtility.GetUtilityMethods().SetSingleDataAsync("4X 1", dic1["4X 1"]); + await _modbusAsciiMachine.BaseUtility.GetUtilityMethods().SetSingleDataAsync("4X 1", dic1["4X 1"]); + await _modbusRtuMachine.BaseUtility.GetUtilityMethods().SetSingleDataAsync("4X 1", dic1["4X 1"]); + var ans = await _modbusTcpMachine.BaseUtility.GetUtilityMethods().GetDatasAsync("4X 1", 1); + var ans2 = await _modbusRtuMachine.BaseUtility.GetUtilityMethods().GetDatasAsync("4X 1", 1); + var ans3 = await _modbusAsciiMachine.BaseUtility.GetUtilityMethods().GetDatasAsync("4X 1", 1); + Assert.AreEqual(ans[0], dic1["4X 1"]); + Assert.AreEqual(ans2[0], dic1["4X 1"]); + Assert.AreEqual(ans3[0], dic1["4X 1"]); + await _modbusTcpMachine.BaseUtility.GetUtilityMethods().SetSingleDataAsync("0X 1", dic2["0X 1"] >= 1); + await _modbusAsciiMachine.BaseUtility.GetUtilityMethods().SetSingleDataAsync("0X 1", dic2["0X 1"] >= 1); + await _modbusRtuMachine.BaseUtility.GetUtilityMethods().SetSingleDataAsync("0X 1", dic2["0X 1"] >= 1); + var ans21 = await _modbusTcpMachine.BaseUtility.GetUtilityMethods().GetDatasAsync("0X 1", 1); + var ans22 = await _modbusRtuMachine.BaseUtility.GetUtilityMethods().GetDatasAsync("0X 1", 1); + var ans23 = await _modbusAsciiMachine.BaseUtility.GetUtilityMethods().GetDatasAsync("0X 1", 1); + Assert.AreEqual(ans21[0] ? 1 : 0, dic2["0X 1"]); + Assert.AreEqual(ans22[0] ? 1 : 0, dic2["0X 1"]); + Assert.AreEqual(ans23[0] ? 1 : 0, dic2["0X 1"]); + } + + [TestCleanup] public void MachineClean() { From 138d5fc23a965444143ffb3573bc0fce2d4d0ed1 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 14 Jun 2017 17:07:48 +0800 Subject: [PATCH 57/62] Version Update to 1.3.9-beta1 --- Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj | 2 +- Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj | 2 +- Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj | 6 ++---- Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj | 6 ++---- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 6 ++---- Modbus.Net/src/Base.Common/BaseMachine.cs | 5 +++++ 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index c473162..ab85ab0 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.Core Modbus.Net Modbus.Net.Core - 1.3.8-beta3 + 1.3.9-beta1 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index 8e9385a..f07bfd1 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.8-beta1 + 1.3.9-beta1 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index df1c440..de8c511 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.8-beta1 + 1.3.9-beta1 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net OPC Implementation @@ -35,9 +35,7 @@ - - C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Configuration.dll - + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index fc381ae..0bfe60c 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.8-beta1 + 1.3.9-beta1 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net Siemens Profinet Implementation @@ -30,9 +30,7 @@ - - C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Configuration.dll - + \ 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 5acf3d2..3cc0c7b 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.8-beta2 + 1.3.9-beta1 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -61,9 +61,7 @@ - - C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Configuration.dll - + diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index ac83417..8d08945 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -591,6 +591,11 @@ namespace Modbus.Net /// public string ConnectionToken => BaseUtility.ConnectionToken; + /// + /// 获取设备的方法集合 + /// + /// 方法集合的类型 + /// 设备的方法集合 public TMachineMethod GetMachineMethods() where TMachineMethod : class, IMachineMethod { if (this is TMachineMethod) From d34952949d82757832e3178b0ee688dd08247834 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 14 Jun 2017 17:52:44 +0800 Subject: [PATCH 58/62] 2017-06-14 update 2 Fix OPC Regex tags combine bug. --- .../Modbus.Net.OPC/AddressFormaterOpc.cs | 2 +- Modbus.Net/Modbus.Net.OPC/ClientExtend.cs | 2 +- .../Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs | 2 +- .../Modbus.Net.OPC/Modbus.Net.OPC.csproj | 2 +- Modbus.Net/Modbus.Net.OPC/OpcConnector.cs | 58 ++++--------------- Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs | 8 ++- Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs | 10 ++-- Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs | 8 ++- .../Modbus.Net.OPC/OpcDaProtocalLinker.cs | 8 ++- Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs | 5 +- Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs | 8 +-- Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs | 8 ++- Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs | 10 ++-- Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs | 8 ++- .../Modbus.Net.OPC/OpcUaProtocalLinker.cs | 8 ++- Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs | 5 +- Modbus.Net/Modbus.Net.OPC/OpcUtility.cs | 4 +- 17 files changed, 71 insertions(+), 85 deletions(-) diff --git a/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs b/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs index afaf426..47d082a 100644 --- a/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs +++ b/Modbus.Net/Modbus.Net.OPC/AddressFormaterOpc.cs @@ -53,7 +53,7 @@ namespace Modbus.Net.OPC var strings = TagGeter(Machine, findAddress); var ans = ""; for (var i = 0; i < strings.Length; i++) - ans += strings[i].Trim().Replace(" ", "") + Seperator; + ans += strings[i].Trim().Replace(" ", "") + '\r'; ans = ans.Substring(0, ans.Length - 1); return ans; } diff --git a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs index 43b4e35..109c537 100644 --- a/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs +++ b/Modbus.Net/Modbus.Net.OPC/ClientExtend.cs @@ -115,7 +115,7 @@ namespace Modbus.Net.OPC /// /// Tag of a node /// - public string Tag { get; set; } + public string[] Tag { get; set; } /// /// Tag splitter of a node diff --git a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs index c1f4827..04053a2 100644 --- a/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs +++ b/Modbus.Net/Modbus.Net.OPC/FBox/FBoxOpcDaManchine.cs @@ -19,7 +19,7 @@ namespace Modbus.Net.OPC.FBox IEnumerable getAddresses, bool keepConnect) : base( ConfigurationManager.AppSettings["FBoxOpcDaHost"] ?? "opcda://localhost/FBoxOpcServer", getAddresses, - keepConnect) + keepConnect, true) { LocalSequence = localSequence; LinkerName = linkerName; diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index de8c511..aab3c11 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.9-beta1 + 1.3.9-beta2 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net OPC Implementation diff --git a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs index e9d42d4..bcfaeb3 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcConnector.cs @@ -24,13 +24,20 @@ namespace Modbus.Net.OPC /// protected IClientExtend Client; + /// + /// 是否开启正则匹配 + /// + protected bool RegexOn { get; set; } + /// /// 构造函数 /// /// 服务端url - protected OpcConnector(string host) + /// 是否开启正则匹配 + protected OpcConnector(string host, bool isRegexOn) { ConnectionToken = host; + RegexOn = isRegexOn; } /// @@ -95,47 +102,6 @@ namespace Modbus.Net.OPC return AsyncHelper.RunSync(() => SendMsgAsync(message)); } - /// - /// 根据括号折叠已经打开的标签 - /// - /// 已经打开的标签 - /// 分割符 - /// 开始字符 - /// 结束字符 - private void FoldWith(List tagSplitList, char splitChar, char startChar, char endChar) - { - for (var i = 0; i < tagSplitList.Count; i++) - if (tagSplitList[i].Count(ch => ch == startChar) > tagSplitList[i].Count(ch => ch == endChar)) - for (var j = i + 1; j < tagSplitList.Count; j++) - if (tagSplitList[j].Contains(endChar)) - { - for (var k = i + 1; k <= j; k++) - { - tagSplitList[i] += splitChar + tagSplitList[i + 1]; - tagSplitList.RemoveAt(i + 1); - } - i--; - break; - } - } - - /// - /// 根据分隔符切分标签 - /// - /// 标签 - /// 分隔符 - /// 分割后的标签 - private string[] SplitTag(string tag, char split) - { - var tagSplitList = tag.Split(split).ToList(); - - FoldWith(tagSplitList, split, '(', ')'); - FoldWith(tagSplitList, split, '[', ']'); - FoldWith(tagSplitList, split, '{', '}'); - - return tagSplitList.ToArray(); - } - /// /// 带返回发送数据 /// @@ -149,9 +115,8 @@ namespace Modbus.Net.OPC { var split = message.Split; var tag = message.Tag; - var tagSplit = SplitTag(tag, split); var rootDirectory = await Client.ExploreFolderAsync(""); - var answerTag = await SearchTag(tagSplit, split, 0, rootDirectory); + var answerTag = await SearchTag(tag, split, 0, rootDirectory); if (answerTag != null) { var result = await Client.ReadAsync(answerTag); @@ -175,8 +140,7 @@ namespace Modbus.Net.OPC var value = message.SetValue; var rootDirectory = await Client.ExploreFolderAsync(""); - var tagSplit = SplitTag(tag, split); - var answerTag = await SearchTag(tagSplit, split, 0, rootDirectory); + var answerTag = await SearchTag(tag, split, 0, rootDirectory); if (answerTag != null) { try @@ -227,7 +191,7 @@ namespace Modbus.Net.OPC foreach (var node in nodes) { var currentTag = node.Tag.Substring(node.Tag.LastIndexOf(split) + 1); - if (Regex.IsMatch(currentTag, tags[deep])) + if (RegexOn && Regex.IsMatch(currentTag, tags[deep]) || !RegexOn && currentTag == tags[deep]) { if (deep == tags.Length - 1) return node.Tag; var subDirectories = await Client.ExploreFolderAsync(node.Tag); diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs index 416aad5..4b30e81 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaConnector.cs @@ -17,7 +17,8 @@ namespace Modbus.Net.OPC /// 构造函数 /// /// Opc DA 服务地址 - protected OpcDaConnector(string host) : base(host) + /// 是否开启正则匹配 + protected OpcDaConnector(string host, bool isRegexOn) : base(host, isRegexOn) { Client = new MyDaClient(new Uri(ConnectionToken)); } @@ -26,12 +27,13 @@ namespace Modbus.Net.OPC /// 根据服务地址生成DA单例 /// /// Opc DA 服务地址 + /// 是否开启正则匹配 /// Opc DA 连接器实例 - public static OpcDaConnector Instance(string host) + public static OpcDaConnector Instance(string host, bool isRegexOn) { if (!_instances.ContainsKey(host)) { - var connector = new OpcDaConnector(host); + var connector = new OpcDaConnector(host, isRegexOn); _instances.Add(host, connector); } return _instances[host]; diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs index 6eed0e3..ed39377 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaMachine.cs @@ -17,10 +17,11 @@ namespace Modbus.Net.OPC /// 连接地址 /// 需要读写的数据 /// 是否保持连接 - public OpcDaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect) + /// 是否开启正则匹配 + public OpcDaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect, bool isRegexOn = false) : base(getAddresses, keepConnect) { - BaseUtility = new OpcDaUtility(connectionString); + BaseUtility = new OpcDaUtility(connectionString, isRegexOn); ((OpcUtility) BaseUtility).GetSeperator += () => ((AddressFormaterOpc) AddressFormater).Seperator; } @@ -47,10 +48,11 @@ namespace Modbus.Net.OPC /// 连接地址 /// 需要读写的数据 /// 是否保持连接 - public OpcDaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect) + /// 是否开启正则匹配 + public OpcDaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect, bool isRegexOn = false) : base(getAddresses, keepConnect) { - BaseUtility = new OpcDaUtility(connectionString); + BaseUtility = new OpcDaUtility(connectionString, isRegexOn); ((OpcUtility) BaseUtility).GetSeperator += () => ((AddressFormaterOpc) AddressFormater).Seperator; } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs index 41cbdc0..47beba8 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocal.cs @@ -9,13 +9,17 @@ namespace Modbus.Net.OPC { private readonly string _host; + private readonly bool _isRegexOn; + /// /// 构造函数 /// /// Opc DA服务地址 - public OpcDaProtocal(string host) + /// 是否开启正则匹配 + public OpcDaProtocal(string host, bool isRegexOn) { _host = host; + _isRegexOn = isRegexOn; } /// @@ -33,7 +37,7 @@ namespace Modbus.Net.OPC /// 是否连接成功 public override async Task ConnectAsync() { - ProtocalLinker = new OpcDaProtocalLinker(_host); + ProtocalLinker = new OpcDaProtocalLinker(_host, _isRegexOn); if (!await ProtocalLinker.ConnectAsync()) return false; return true; diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs index 7da896b..265a1a8 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaProtocalLinker.cs @@ -10,7 +10,8 @@ namespace Modbus.Net.OPC /// /// 构造函数 /// - public OpcDaProtocalLinker() : this(ConfigurationManager.AppSettings["OpcDaHost"]) + /// 是否开启正则匹配 + public OpcDaProtocalLinker(bool isRegexOn) : this(ConfigurationManager.AppSettings["OpcDaHost"], isRegexOn) { } @@ -18,9 +19,10 @@ namespace Modbus.Net.OPC /// 构造函数 /// /// Opc DA服务地址 - public OpcDaProtocalLinker(string host) + /// 是否开启正则匹配 + public OpcDaProtocalLinker(string host, bool isRegexOn) { - BaseConnector = OpcDaConnector.Instance(host); + BaseConnector = OpcDaConnector.Instance(host, isRegexOn); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs index 5415754..3acb95e 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcDaUtility.cs @@ -9,9 +9,10 @@ /// 构造函数 /// /// 连接地址 - public OpcDaUtility(string connectionString) : base(connectionString) + /// 是否开启正则匹配 + public OpcDaUtility(string connectionString, bool isRegexOn = false) : base(connectionString) { - Wrapper = new OpcDaProtocal(ConnectionString); + Wrapper = new OpcDaProtocal(ConnectionString, isRegexOn); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs index 0b7d66a..30c2501 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs @@ -25,7 +25,7 @@ /// /// 标签 /// 分隔符 - public ReadRequestOpcInputStruct(string tag, char split) + public ReadRequestOpcInputStruct(string[] tag, char split) { Tag = tag; Split = split; @@ -34,7 +34,7 @@ /// /// 标签 /// - public string Tag { get; } + public string[] Tag { get; } /// /// 分隔符 @@ -111,7 +111,7 @@ /// 标签 /// 分隔符 /// 写入的数据 - public WriteRequestOpcInputStruct(string tag, char split, object setValue) + public WriteRequestOpcInputStruct(string[] tag, char split, object setValue) { Tag = tag; Split = split; @@ -121,7 +121,7 @@ /// /// 标签 /// - public string Tag { get; } + public string[] Tag { get; } /// /// 分隔符 diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs index 498a3e6..acae757 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaConnector.cs @@ -17,7 +17,8 @@ namespace Modbus.Net.OPC /// 构造函数 /// /// Opc UA 服务地址 - protected OpcUaConnector(string host) : base(host) + /// 是否开启正则匹配 + protected OpcUaConnector(string host, bool isRegexOn) : base(host, isRegexOn) { Client = new MyUaClient(new Uri(ConnectionToken)); } @@ -26,12 +27,13 @@ namespace Modbus.Net.OPC /// 根据地址获取UA连接器单例 /// /// Opc UA服务地址 + /// 是否开启正则匹配 /// OPC UA实例 - public static OpcUaConnector Instance(string host) + public static OpcUaConnector Instance(string host, bool isRegexOn) { if (!_instances.ContainsKey(host)) { - var connector = new OpcUaConnector(host); + var connector = new OpcUaConnector(host, isRegexOn); _instances.Add(host, connector); } return _instances[host]; diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs index 815d482..584a4eb 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaMachine.cs @@ -17,10 +17,11 @@ namespace Modbus.Net.OPC /// 连接地址 /// 需要读写的数据 /// 是否保持连接 - public OpcUaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect) + /// 是否开启正则匹配 + public OpcUaMachine(string connectionString, IEnumerable> getAddresses, bool keepConnect, bool isRegexOn = false) : base(getAddresses, keepConnect) { - BaseUtility = new OpcUaUtility(connectionString); + BaseUtility = new OpcUaUtility(connectionString, isRegexOn); ((OpcUtility) BaseUtility).GetSeperator += () => ((AddressFormaterOpc) AddressFormater).Seperator; } @@ -47,10 +48,11 @@ namespace Modbus.Net.OPC /// 连接地址 /// 需要读写的数据 /// 是否保持连接 - public OpcUaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect) + /// 是否开启正则匹配 + public OpcUaMachine(string connectionString, IEnumerable getAddresses, bool keepConnect, bool isRegexOn = false) : base(getAddresses, keepConnect) { - BaseUtility = new OpcUaUtility(connectionString); + BaseUtility = new OpcUaUtility(connectionString, isRegexOn); ((OpcUtility) BaseUtility).GetSeperator += () => ((AddressFormaterOpc) AddressFormater).Seperator; } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs index f358e98..32d07fc 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocal.cs @@ -9,13 +9,17 @@ namespace Modbus.Net.OPC { private readonly string _host; + private readonly bool _isRegexOn; + /// /// 构造函数 /// /// Opc UA服务地址 - public OpcUaProtocal(string host) + /// 是否开启正则匹配 + public OpcUaProtocal(string host, bool isRegexOn) { _host = host; + _isRegexOn = isRegexOn; } /// @@ -33,7 +37,7 @@ namespace Modbus.Net.OPC /// 是否连接成功 public override async Task ConnectAsync() { - ProtocalLinker = new OpcUaProtocalLinker(_host); + ProtocalLinker = new OpcUaProtocalLinker(_host, _isRegexOn); if (!await ProtocalLinker.ConnectAsync()) return false; return true; } diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs index 34dc6cb..d4ed0af 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaProtocalLinker.cs @@ -10,7 +10,8 @@ namespace Modbus.Net.OPC /// /// 构造函数 /// - public OpcUaProtocalLinker() : this(ConfigurationManager.AppSettings["OpcUaHost"]) + /// 是否开启正则匹配 + public OpcUaProtocalLinker(bool isRegexOn) : this(ConfigurationManager.AppSettings["OpcUaHost"], isRegexOn) { } @@ -18,9 +19,10 @@ namespace Modbus.Net.OPC /// 构造函数 /// /// Opc UA服务地址 - public OpcUaProtocalLinker(string host) + /// 是否开启正则匹配 + public OpcUaProtocalLinker(string host, bool isRegexOn) { - BaseConnector = OpcUaConnector.Instance(host); + BaseConnector = OpcUaConnector.Instance(host, isRegexOn); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs index e144afe..e4db506 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUaUtility.cs @@ -9,9 +9,10 @@ /// 构造函数 /// /// 连接地址 - public OpcUaUtility(string connectionString) : base(connectionString) + /// 是否开启正则匹配 + public OpcUaUtility(string connectionString, bool isRegexOn = false) : base(connectionString) { - Wrapper = new OpcUaProtocal(ConnectionString); + Wrapper = new OpcUaProtocal(ConnectionString, isRegexOn); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs index 050b2e6..ea72ded 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcUtility.cs @@ -55,7 +55,7 @@ namespace Modbus.Net.OPC try { var split = GetSeperator?.Invoke() ?? '/'; - var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, split); + var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress.Split('\r'), split); var readRequestOpcOutputStruct = await Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], @@ -80,7 +80,7 @@ namespace Modbus.Net.OPC try { var split = GetSeperator?.Invoke() ?? '/'; - var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, split, setContents[0]); + var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress.Split('\r'), split, setContents[0]); var writeRequestOpcOutputStruct = await Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestOpcProtocal)], From df072fa8ffb7fde41ecd91d07bc3b584e6b9773b Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 14 Jun 2017 17:58:01 +0800 Subject: [PATCH 59/62] Update Readme.md --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 427dacd..c107f8e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,12 @@ Platform Supported * .NET Framework 4.5 * .NET Standard 1.3 -## RoadMap +Thanks +------------------- +Resharper -- Offers Modbus.Net team community lisence. + +RoadMap +------------------- ### Version 1.2.0 * Modbus ASCII Support (Complete) @@ -80,11 +85,12 @@ Platform Supported * AddressCombiner need to add maximum length now. Combiner will consider the maximum length when combining addresses (Complete) ### Version 1.3.8 -* Change Resx to app.config or appsettings.json, now you can set default params there (Complete) +* Change Resx to appsettings.json, now you can set default params there (Complete) * Change ISpecialProtocalUnit to SpecialProtocalUnitAttribute (Complete) ### Version 1.3.9 -* Modbus Single Write for Coil and Reg (05 and 06) (In Road) +* Modbus Single Write for Coil and Reg (05 and 06) (Complete) +* Fix OPC tag combine problem (Complete) ### * Github wiki Document Chinese (Not Complete) From 7b99fd1ac839ed430ece76c0275ccdbc0a0eaac0 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Wed, 14 Jun 2017 17:59:14 +0800 Subject: [PATCH 60/62] update Readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c107f8e..c89a9ad 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ RoadMap * AddressCombiner need to add maximum length now. Combiner will consider the maximum length when combining addresses (Complete) ### Version 1.3.8 -* Change Resx to appsettings.json, now you can set default params there (Complete) +* Change Resx to appsettings.json, now you can set default params there (Complete - CORE ONLY) * Change ISpecialProtocalUnit to SpecialProtocalUnitAttribute (Complete) ### Version 1.3.9 From a6d3e7a223f56384f5a10647c40fa68b1475e5c7 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 30 Jun 2017 11:03:50 +0800 Subject: [PATCH 61/62] 2017-06-30 Update 1 Final Package to 1.3.9 --- .../Modbus.Net.Core/Modbus.Net.Core.csproj | 2 +- .../Modbus.Net.Modbus/Modbus.Net.Modbus.csproj | 5 ++++- Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj | 2 +- .../Modbus.Net.Siemens.csproj | 2 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 3 +-- README.md | 6 +++--- pic/PNG/CHS/内部图1.png | Bin 0 -> 6403 bytes pic/PNG/CHS/内部图2.png | Bin 0 -> 10087 bytes pic/PNG/CHS/内部图3.png | Bin 0 -> 7680 bytes pic/PNG/CHS/内部图4.png | Bin 0 -> 7160 bytes pic/PNG/CHS/内部图5.png | Bin 0 -> 15684 bytes pic/PNG/CHS/内部图6.png | Bin 0 -> 6497 bytes pic/PNG/CHS/外部图1.png | Bin 0 -> 9412 bytes pic/PNG/CHS/外部图2.png | Bin 0 -> 5001 bytes pic/PNG/CHS/外部图3.png | Bin 0 -> 2814 bytes pic/PNG/CHS/外部图4.png | Bin 0 -> 5609 bytes pic/PNG/CHS/外部图5.png | Bin 0 -> 5609 bytes pic/PNG/CHS/外部图6.png | Bin 0 -> 3221 bytes pic/PNG/CHS/架构图.png | Bin 0 -> 11524 bytes pic/{ => PNG/CHS}/模块图.png | Bin pic/PNG/CHS/类图Modbus.png | Bin 0 -> 38617 bytes pic/PNG/CHS/类图OPC.png | Bin 0 -> 31334 bytes pic/PNG/CHS/类图Siemens.png | Bin 0 -> 28131 bytes pic/PNG/ENG/Architecture Graph.png | Bin 0 -> 12174 bytes pic/PNG/ENG/Class Modbus.png | Bin 0 -> 38617 bytes pic/PNG/ENG/Class OPC.png | Bin 0 -> 31334 bytes pic/PNG/ENG/Class Siemens.png | Bin 0 -> 28131 bytes pic/PNG/ENG/Inner Graph 1.png | Bin 0 -> 6219 bytes pic/PNG/ENG/Inner Graph 2.png | Bin 0 -> 9447 bytes pic/PNG/ENG/Inner Graph 3.png | Bin 0 -> 7348 bytes pic/PNG/ENG/Inner Graph 4.png | Bin 0 -> 6079 bytes pic/PNG/ENG/Inner Graph 5.png | Bin 0 -> 15605 bytes pic/PNG/ENG/Inner Graph 6.png | Bin 0 -> 6086 bytes pic/PNG/ENG/Module Graph.png | Bin 0 -> 15179 bytes pic/PNG/ENG/Outer Graph 1.png | Bin 0 -> 8897 bytes pic/PNG/ENG/Outer Graph 2.png | Bin 0 -> 5001 bytes pic/PNG/ENG/Outer Graph 3.png | Bin 0 -> 2814 bytes pic/PNG/ENG/Outer Graph 4.png | Bin 0 -> 5739 bytes pic/PNG/ENG/Outer Graph 5.png | Bin 0 -> 5499 bytes pic/PNG/ENG/Outer Graph 6.png | Bin 0 -> 3121 bytes pic/UML/CHS/内部图1.vsdx | Bin 0 -> 26810 bytes pic/UML/CHS/内部图2.vsdx | Bin 0 -> 28432 bytes pic/UML/CHS/内部图3.vsdx | Bin 0 -> 25540 bytes pic/UML/CHS/内部图4.vsdx | Bin 0 -> 25792 bytes pic/UML/CHS/内部图5.vsdx | Bin 0 -> 37002 bytes pic/UML/CHS/内部图6.vsdx | Bin 0 -> 28187 bytes pic/UML/CHS/外部图1.vsdx | Bin 0 -> 25813 bytes pic/UML/CHS/外部图2.vsdx | Bin 0 -> 23098 bytes pic/UML/CHS/外部图3.vsdx | Bin 0 -> 24144 bytes pic/UML/CHS/外部图4.vsdx | Bin 0 -> 24461 bytes pic/UML/CHS/外部图5.vsdx | Bin 0 -> 23847 bytes pic/UML/CHS/外部图6.vsdx | Bin 0 -> 22257 bytes pic/UML/CHS/架构图.vsdx | Bin 0 -> 34692 bytes pic/UML/CHS/模块图.vsdx | Bin 0 -> 38563 bytes pic/UML/CHS/类图Modbus.vsdx | Bin 0 -> 70225 bytes pic/UML/CHS/类图OPC.vsdx | Bin 0 -> 67802 bytes pic/UML/CHS/类图Siemens.vsdx | Bin 0 -> 50662 bytes pic/UML/ENG/Architecture Graph.vsdx | Bin 0 -> 34810 bytes pic/UML/ENG/Class Modbus.vsdx | Bin 0 -> 70226 bytes pic/UML/ENG/Class OPC.vsdx | Bin 0 -> 67802 bytes pic/UML/ENG/Class Siemens.vsdx | Bin 0 -> 50662 bytes pic/UML/ENG/Inner Graph 1.vsdx | Bin 0 -> 26727 bytes pic/UML/ENG/Inner Graph 2.vsdx | Bin 0 -> 28214 bytes pic/UML/ENG/Inner Graph 3.vsdx | Bin 0 -> 25193 bytes pic/UML/ENG/Inner Graph 4.vsdx | Bin 0 -> 25641 bytes pic/UML/ENG/Inner Graph 5.vsdx | Bin 0 -> 36979 bytes pic/UML/ENG/Inner Graph 6.vsdx | Bin 0 -> 28162 bytes pic/UML/ENG/Module Graph.vsdx | Bin 0 -> 38817 bytes pic/UML/ENG/Outer Graph 1.vsdx | Bin 0 -> 25756 bytes pic/UML/ENG/Outer Graph 2.vsdx | Bin 0 -> 23097 bytes pic/UML/ENG/Outer Graph 3.vsdx | Bin 0 -> 24143 bytes pic/UML/ENG/Outer Graph 4.vsdx | Bin 0 -> 24465 bytes pic/UML/ENG/Outer Graph 5.vsdx | Bin 0 -> 23895 bytes pic/UML/ENG/Outer Graph 6.vsdx | Bin 0 -> 22038 bytes pic/内部图1.png | Bin 5496 -> 0 bytes pic/内部图2.png | Bin 10145 -> 0 bytes pic/内部图3.png | Bin 6862 -> 0 bytes pic/内部图4.png | Bin 6153 -> 0 bytes pic/内部图5.png | Bin 13840 -> 0 bytes pic/内部图6.png | Bin 5815 -> 0 bytes pic/外部图1.png | Bin 9191 -> 0 bytes pic/外部图2.png | Bin 5171 -> 0 bytes pic/外部图3.png | Bin 2946 -> 0 bytes pic/外部图4.png | Bin 5590 -> 0 bytes pic/外部图5.png | Bin 6154 -> 0 bytes pic/外部图6.png | Bin 3122 -> 0 bytes pic/架构图.png | Bin 12098 -> 0 bytes pic/类图Modbus.png | Bin 31118 -> 0 bytes pic/类图OPC.png | Bin 25158 -> 0 bytes pic/类图Siemens.png | Bin 22456 -> 0 bytes 90 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 pic/PNG/CHS/内部图1.png create mode 100644 pic/PNG/CHS/内部图2.png create mode 100644 pic/PNG/CHS/内部图3.png create mode 100644 pic/PNG/CHS/内部图4.png create mode 100644 pic/PNG/CHS/内部图5.png create mode 100644 pic/PNG/CHS/内部图6.png create mode 100644 pic/PNG/CHS/外部图1.png create mode 100644 pic/PNG/CHS/外部图2.png create mode 100644 pic/PNG/CHS/外部图3.png create mode 100644 pic/PNG/CHS/外部图4.png create mode 100644 pic/PNG/CHS/外部图5.png create mode 100644 pic/PNG/CHS/外部图6.png create mode 100644 pic/PNG/CHS/架构图.png rename pic/{ => PNG/CHS}/模块图.png (100%) create mode 100644 pic/PNG/CHS/类图Modbus.png create mode 100644 pic/PNG/CHS/类图OPC.png create mode 100644 pic/PNG/CHS/类图Siemens.png create mode 100644 pic/PNG/ENG/Architecture Graph.png create mode 100644 pic/PNG/ENG/Class Modbus.png create mode 100644 pic/PNG/ENG/Class OPC.png create mode 100644 pic/PNG/ENG/Class Siemens.png create mode 100644 pic/PNG/ENG/Inner Graph 1.png create mode 100644 pic/PNG/ENG/Inner Graph 2.png create mode 100644 pic/PNG/ENG/Inner Graph 3.png create mode 100644 pic/PNG/ENG/Inner Graph 4.png create mode 100644 pic/PNG/ENG/Inner Graph 5.png create mode 100644 pic/PNG/ENG/Inner Graph 6.png create mode 100644 pic/PNG/ENG/Module Graph.png create mode 100644 pic/PNG/ENG/Outer Graph 1.png create mode 100644 pic/PNG/ENG/Outer Graph 2.png create mode 100644 pic/PNG/ENG/Outer Graph 3.png create mode 100644 pic/PNG/ENG/Outer Graph 4.png create mode 100644 pic/PNG/ENG/Outer Graph 5.png create mode 100644 pic/PNG/ENG/Outer Graph 6.png create mode 100644 pic/UML/CHS/内部图1.vsdx create mode 100644 pic/UML/CHS/内部图2.vsdx create mode 100644 pic/UML/CHS/内部图3.vsdx create mode 100644 pic/UML/CHS/内部图4.vsdx create mode 100644 pic/UML/CHS/内部图5.vsdx create mode 100644 pic/UML/CHS/内部图6.vsdx create mode 100644 pic/UML/CHS/外部图1.vsdx create mode 100644 pic/UML/CHS/外部图2.vsdx create mode 100644 pic/UML/CHS/外部图3.vsdx create mode 100644 pic/UML/CHS/外部图4.vsdx create mode 100644 pic/UML/CHS/外部图5.vsdx create mode 100644 pic/UML/CHS/外部图6.vsdx create mode 100644 pic/UML/CHS/架构图.vsdx create mode 100644 pic/UML/CHS/模块图.vsdx create mode 100644 pic/UML/CHS/类图Modbus.vsdx create mode 100644 pic/UML/CHS/类图OPC.vsdx create mode 100644 pic/UML/CHS/类图Siemens.vsdx create mode 100644 pic/UML/ENG/Architecture Graph.vsdx create mode 100644 pic/UML/ENG/Class Modbus.vsdx create mode 100644 pic/UML/ENG/Class OPC.vsdx create mode 100644 pic/UML/ENG/Class Siemens.vsdx create mode 100644 pic/UML/ENG/Inner Graph 1.vsdx create mode 100644 pic/UML/ENG/Inner Graph 2.vsdx create mode 100644 pic/UML/ENG/Inner Graph 3.vsdx create mode 100644 pic/UML/ENG/Inner Graph 4.vsdx create mode 100644 pic/UML/ENG/Inner Graph 5.vsdx create mode 100644 pic/UML/ENG/Inner Graph 6.vsdx create mode 100644 pic/UML/ENG/Module Graph.vsdx create mode 100644 pic/UML/ENG/Outer Graph 1.vsdx create mode 100644 pic/UML/ENG/Outer Graph 2.vsdx create mode 100644 pic/UML/ENG/Outer Graph 3.vsdx create mode 100644 pic/UML/ENG/Outer Graph 4.vsdx create mode 100644 pic/UML/ENG/Outer Graph 5.vsdx create mode 100644 pic/UML/ENG/Outer Graph 6.vsdx delete mode 100644 pic/内部图1.png delete mode 100644 pic/内部图2.png delete mode 100644 pic/内部图3.png delete mode 100644 pic/内部图4.png delete mode 100644 pic/内部图5.png delete mode 100644 pic/内部图6.png delete mode 100644 pic/外部图1.png delete mode 100644 pic/外部图2.png delete mode 100644 pic/外部图3.png delete mode 100644 pic/外部图4.png delete mode 100644 pic/外部图5.png delete mode 100644 pic/外部图6.png delete mode 100644 pic/架构图.png delete mode 100644 pic/类图Modbus.png delete mode 100644 pic/类图OPC.png delete mode 100644 pic/类图Siemens.png diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index ab85ab0..86df934 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.Core Modbus.Net Modbus.Net.Core - 1.3.9-beta1 + 1.3.9 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index f07bfd1..0a9cd54 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.9-beta1 + 1.3.9 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net.Modbus @@ -34,4 +34,7 @@ + + + \ 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 aab3c11..b44303a 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.9-beta2 + 1.3.9 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net OPC Implementation diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 0bfe60c..13cf6d5 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.9-beta1 + 1.3.9 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net Siemens Profinet Implementation diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index 3cc0c7b..d0395eb 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.9-beta1 + 1.3.9 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -57,7 +57,6 @@ - diff --git a/README.md b/README.md index c89a9ad..4cef080 100644 --- a/README.md +++ b/README.md @@ -92,9 +92,9 @@ RoadMap * Modbus Single Write for Coil and Reg (05 and 06) (Complete) * Fix OPC tag combine problem (Complete) -### -* Github wiki Document Chinese (Not Complete) -* Github wiki Document English (In Road) +### 1.3.X Other +* Github wiki Document Chinese (Complete) +* Github wiki Document English (Complete) ### Version 1.4.0 * BaseController (In Road) diff --git a/pic/PNG/CHS/内部图1.png b/pic/PNG/CHS/内部图1.png new file mode 100644 index 0000000000000000000000000000000000000000..040fbd02d6927022ca98bca3397c3b9ad5cdbfff GIT binary patch literal 6403 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 WJv>IZ4E*B)WNKt-SbpB)_J08>jLcvF literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/内部图2.png b/pic/PNG/CHS/内部图2.png new file mode 100644 index 0000000000000000000000000000000000000000..afc974756b1189341de8945d8e8c4f8d80660331 GIT binary patch literal 10087 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 literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/内部图4.png b/pic/PNG/CHS/内部图4.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed915f735da9ab6c3692b11536dea8be4c576c7 GIT binary patch literal 7160 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 bhglq-cTE-qhV^aV=z-w+CVF|g_QC%JuM(rJ literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/内部图5.png b/pic/PNG/CHS/内部图5.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4af3381860f9b9738396fe81c4511e714f1dfb GIT binary patch literal 15684 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 OL24>mm-8-}`~5Eo?bU(+ literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/内部图6.png b/pic/PNG/CHS/内部图6.png new file mode 100644 index 0000000000000000000000000000000000000000..a70445c85ff0ba2326ae6156c81b08cb027e5520 GIT binary patch literal 6497 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 Q-y#q*Bg^v@=Ungo2fy!7X8-^I literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/外部图1.png b/pic/PNG/CHS/外部图1.png new file mode 100644 index 0000000000000000000000000000000000000000..e70967e290c911e15b7b4e8145357fec93c4959c GIT binary patch literal 9412 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 literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/外部图2.png b/pic/PNG/CHS/外部图2.png new file mode 100644 index 0000000000000000000000000000000000000000..c52aaa6a7ded513273a81fd3ccb80413342e16b7 GIT binary patch literal 5001 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 literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/外部图4.png b/pic/PNG/CHS/外部图4.png new file mode 100644 index 0000000000000000000000000000000000000000..2e31e24fee31e4754b2968e047b138b9b95646fa GIT binary patch literal 5609 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 I^FRFhKSkY{{r~^~ literal 0 HcmV?d00001 diff --git a/pic/PNG/CHS/外部图5.png b/pic/PNG/CHS/外部图5.png new file mode 100644 index 0000000000000000000000000000000000000000..9b34f9294b3d54d24e03dbe14d00ca127d369cac GIT binary patch literal 5609 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 literal 0 HcmV?d00001 diff --git a/pic/模块图.png b/pic/PNG/CHS/模块图.png similarity index 100% rename from pic/模块图.png rename to pic/PNG/CHS/模块图.png diff --git a/pic/PNG/CHS/类图Modbus.png b/pic/PNG/CHS/类图Modbus.png new file mode 100644 index 0000000000000000000000000000000000000000..b9964d84b373eef8ff388c33de735f5b38665f00 GIT binary patch literal 38617 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�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 literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Architecture Graph.png b/pic/PNG/ENG/Architecture Graph.png new file mode 100644 index 0000000000000000000000000000000000000000..cc11929b318cb5204267d1c45bcacc536c354b24 GIT binary patch literal 12174 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 Z{{wqK#_y;Z=%E)wm|DXNzq)kizX0$G?AibT literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Class Modbus.png b/pic/PNG/ENG/Class Modbus.png new file mode 100644 index 0000000000000000000000000000000000000000..b9964d84b373eef8ff388c33de735f5b38665f00 GIT binary patch literal 38617 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�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 literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Inner Graph 1.png b/pic/PNG/ENG/Inner Graph 1.png new file mode 100644 index 0000000000000000000000000000000000000000..bb856921721ae0d20ae4179aee78e91b473f5ee1 GIT binary patch literal 6219 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 U078!rxPOOOnAjK>p1Bz>% literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Inner Graph 2.png b/pic/PNG/ENG/Inner Graph 2.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b768086c613213f149ef9134a3bc01be0c56fc GIT binary patch literal 9447 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 literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Inner Graph 3.png b/pic/PNG/ENG/Inner Graph 3.png new file mode 100644 index 0000000000000000000000000000000000000000..892a835287d39591fc16247aae0a386c5f59e6a1 GIT binary patch literal 7348 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%0Dk@V$v^*_fKFI&a#q_{t7^Xbv9 z{5t1|FCt{K2J^>r-uL3XoJa%9^S=dF8htb96(|r_2gYtH)x36GEUYffJ1xodIw;L8 z649@}3?B>CZAFZTEs+L$Fw=Q(m3UN;i%3+ zkM>qlTcB=^oGm`dS`td#hUm?^bU(UndhzZ;q^jg8EtWe zK;+3}jQkTV%jbnTm07?ekA>OFv0`W&K`B1^$feiz>5Yderm^?F%`B;6SqJ-Aoj4B? zu#BV9QdNaZJoO^(IAyD1bySuS%g(N-CtL~r)EWH%aLC@b?!`$z3Tw1Y0|!q3hl%5c zhU;J^YiL{3T~9%VEJ3fy^NdERW7V{BC~xv*AfJna;^xU^9c908cd9Bi4H~Mz-zEg= zdNsT|p?LEpoUr2WRQ`z^+0?OU@x}3-*$sS2iUGjU{PQO2C99n)el8PRQh7z42w5&6=Rx_awq$DDp*;;7CgK^Qq~Q9UDH zE*&-U+Cz~xHT1Mglk*=FO8Yogf5;Lg?L2Tf(?OkXe9mIw>2>+X&>``nTuciVK1KX7 z?LDtv7v~0#2$=X|}19!mDqU>BM5OwyHAR7fY zYDr?8tiRcxVR#{>2JK4Z=fuFQ5$j%u(;8(87KUPIDEe)jfr_bjJ?KyH32+TpDF1Oh z;muvL-okux;d}8UIk9tjhNQEGiOQvvXN}lr6ruE>WlKt@LYS@bfBs;5zJ(*9T_wv& zQJcW=v$r{*3%0p?dc^NY(Nx2){No^U{UVf{=4K~Y^}0hhv@12b8`il8=Ii|74JOoeA1wy>%tK1Z7&wR$tVrm;X$71&Qxe4`z@u5@99>= zO43kXejx+PnSHCVRcIe3DL70K8D=$)DrI&Wz{jrpU9 z5(ICdZoC=IbG|0nXc`<|e3fAZ1i0t_uw-t#lSBy>LaAXH^n0qh23fuimi?i5e zzY%_Udcs`;)CYczlVUQPFf^Oa<+|2}Dr}Mw&L@S+Rno<|y!h^*td7Q79o8%j#hUeI z{P>xQ8TASodZv{Ctx0&4Cs(x)2#FV&AI7=Y zW*KuhngjarWN&kil#Ar7VOS*R1>2+MQdo zqOv`fvR{DV1-1k#)3*Mh=gk0RiR#HWw;!1%D!HND4G|$G>|6i9Sa0)FJ@ny`1h<}iS__BqLD8*w_|WemNX^f=liNR;pg!&R`ZH@X zQmlvmTO6N*f@V6zquPA>NvR1ytnvJRSEQYA!mTD zguDW!735E1phv88>7RJ9wXr-SRXA#zfE&#otFB;K$Lc{YyqY<1T}DIEB-r^uT#!~J zOE=|M^}MHo+pbR!m`U3d5Q&KP6x+HWYpEt)qHp*Nq>EU%@A|osN1k@0gQg*?T=Uws z^zCY}Osg!)b;CIut~Fxog$U?sfJO)g2y45+4w91;tup!**#)dgU*RGMW+S`w=2Oe&RO_lW3=0_f`D@td}aTB2BOkN+;d%~xX9A1 z`q!!ot^GASDIE{xPY%f&H|Eaw+X#||Vgk?HF{MA+?t~3~tQvY!=!3PTvqjmZsdy=c zKkoYOB6vxGg+3;zeZ8~8$$Q@bEnD8l+`w12-ipPh4(Kna&rvr(+I-e{zE5q(6``=H zJNPR6V6cPuAiw!DOB)vLQ#+RmBxY^vOiktWL)$9OY6rGz${bS^3QGOE8O%e)1{i%h u?F8lE&ntX=E8r6=D)|q(zn9-#miXnofB>HP3wYBAF*Y#MFFSwb?q2}Xh@F}M literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Inner Graph 4.png b/pic/PNG/ENG/Inner Graph 4.png new file mode 100644 index 0000000000000000000000000000000000000000..68b98cd3f5cbb92f4b974935b98205487e4d75f8 GIT binary patch literal 6079 zcmd^D2~?BUw#H)hI)P7(6hzS5IuQmzWfY@Q8EOGRMj-?u78yb)Lokd|TX+p1Dh*L0 zL$SABHo3We?yaS@3a6#@(V;(m1gtoPbwGe&Rf4z6Nv(R8;RG;Q z9dW|_gq9YiV1qL3V_?26&NVPWOG~Fi^Iz48tP0oC((`fq{DjY?5b@C61VfjBM`0&U zaCi6ht@Sxk@05M-WgqrV*dx`dZ@vlBLp^^!{>7Pt&!3+GzM9`bSTy~J{dvU zkz~T!hxCyNXx9tYbR+79gM8~QE08w)tmQ82e;87;F*_Y!Ryxei7X%RQeo~jUzf^oR z{VqP!4&39=DU)O%V4$VQ{q*f_4AK&I(|%{ zI*bWpf5Nr5^~`Z~*%tklj?F9Q{ZszhAqaKkmmH$6>p@jRcLXC8Stx-(AdmLVImL&h z-N^9PJ5}P3co|9Ta+++YF09Ts(#f?Jk1lYlb!x098@)*RlBNR<-$%40RN90=^v$yO zxfGm3-!t`N)v&4KSIHTr^s4MRxO;l(qdk1MO)y8$A%SsTyF%0CKd*S3yC6UBLPRpp=5=Qz&^5thk!Or7Pj zaqgt#v6J{@M5EcLPRxJgnPhp?j%H-=3`b)QW=(WevvL@I31c-AeeCj)*#As8xG0Kx zDCTa6z_6(|9U6`rubg{ULY9jYy%2{jM1t)BBZmg<7IdcavsEc*c1_`5*@&Payiove zdxslzBh7cn4{`Y5ZEg~!)oijniWtkYxSanGahd0{@!#E<|Jq=NX0~Ulhy9LwcYzld z#eCpHU1jw}2!+GpAV=DpHeI`pSw*?`$!7d-4SUGESFc_zEF|%@^nZ`;{XKwOCX@B` z`F@x@NQ!|52M33QP&Zxkl44Xej`eY8lQoYk;m2csYba`k8y`zsRxOS2*F4#eX4co& zvwC}hYu67P&<+174#|_TB98_X1C(4?Sa|g+@DC|DG&tCrx>S$2oCh%B(~u+*385Wc z{ySP~EC9~?b!Wlr*RQF8iSuXhv6Am~*IHxM89}52#6zB4&!HV5P4EQ5qd~*69`*f@ zvHqPUfx{9;v#0GKa&`Z8^@TQ8T}zrXGn63A3?!pP^+)}(orr>qjzfN`a&wG5d0;#Q z&x#(~yN^E~g0C;8^@T&5(nDkazrwyJCZH+VEUVt{K&dWPGayD{Ly(9J2zuLG#*P;nB(FXMn>;r9=|TY6-2rhJ9g1i5hT)_PsfUM0EE388sy9!Pw)?W# z8wSF|)02^|=(kpo6uT=UKMmdbTd&{ySF?x#kBEria=8fYa^eTx0~vU6MWyH^Kxmt; zd8}Yc2m}}u3i#dC-*UM3jwB@Wm`tWnc!94q@rKOHbogVkW?y%XWGLzomlLJ_Q{ecK#mdQMpE}s{X8GtJSN^ zZ@zYtg-KtY5xjX*uKbgqQrcqyQO%!)>UDN@R(vfs+zex3u*MIE+tc~h+QJCRmiyFI z-mZ!Py4Of*y=tq0Ph5PPPv$TnD{i;uLzGPaRvDCSRxo`(=Xa(vy&a@3TDayip{lv#q z8}$0xy?`|)f7yMOve75csq&9+;NyTif7qaYkQHeAAih2B*m{7MnA;2I6zA;~y&0`{ zt0^T#DYBZ;y8!mNP>Q=~?!_1^S0gv3tMc7dnP07G_GH6F#Vz@lV+(QY#ifDy;foLB z6&OI7qPYkP4qvc0L3hwnqbIK}YwwZZ&2(MlHQnJDGa37n%YBB%SuA z2+z0Gjd8||-9vDIw8aW|(}p%{u_p7cah{`#nB*Mn=ExCm+k>e~#>!OGNPD`2qa$L+uATn?seZ*- zr6&|F$mym7Q{Q4{k7mzqu|l~qFBuWz>-4SKUQhVsjopQ}ZU?Ew+L9`Cf@~aon*@9BFt8s8Y)K!Y9VYnHhMCgzcaf2cV69UDA(jF&skVbVS)7 zpueu^?eJOg{~ja$OO>q(WlQjjL|e73KP!XnF`@2ASeW2mu)OWxQNuaK$o}~4qIQ#Q zn{^vkSHXOq$n%tcZ2CmK#mn-^2a!b{NouifmhO{B^0ovX9HmGy(zDX@Q$rMyb%Bk6aMbF)Aq_VD~l*notCj=@iN2B06_#3$U0Z#MvtPDXsZ6iB;NhK)_ct15#8{zREU ztP8GMpzX3&gQ>a-^QeZ!jUy{d(<7NH%4UQF3WWkOnYJlfWFW;^@4U$pl^1(p?57qw zGQ7A+UYlq`_bT&keIjA2z*m~A5L0ztcUR|PU$mQ6B8}Qg@~RYJHIbiQ+CK+AKVOKW z6<+fm#pK@?ia#s=p&3r2(S&B<&{T(YfqT>svL8HnAQFl0&!D#42M}0KPfu=c?k_WW zt0|g^kyhSs#mxgW-7t!@QaV2VgzxrbavVS}3&saNs|OGT8OER@4~S$yUcuWS z2mG%!05It43O{lr06wWUDO!+uTJJeCR{__b@?}n{Pu2&|i^^hisRYQ(Ngva!Vhd1D z=!i+b-<2e2ZL7~lF7u+|@9V=}i~7~Mk=X9=!&5Y(tjCM8I;!2r^opvM2d$Fm4K1^} z!`MidIUEtb?qwPfq*8+@E8M79D7GtcIsWhL{pKAFvLkH`SvA;>UunHe{1PkZ`1#!7 zi;5S&(CUJzAA`=HJpwZ+Ix&w)f)t4lhkb{6XTY1~z?jbWgvXiGJMU$h06R|K89fa| zP>NYqz(<+3dc2tvybO_7Sp5mmfFy^FCcQ}O~UXlrB3NEk^B>#_%d*JdchG!0^gTvDhX@Wzvx z*gdtWzAH%?jqb$J=pl?*=DN{(bI9Z?@p8w4wd!H-3fkPK_Nj%rIe;;`Z^d)u*X#7E z;QY4G5D|)3QB3Xx`!Tlnz^*sfIIP&W_tOxZ0>uDHW9(Q#R=_$Cs$m zFD+AC871b`bz^-OgRo%`f;onrBCHTJ1PpHn6Uvvy!{=u*9B%8XfUK@bf6=YSGL!+5 zUXqcP%ohg6hZDW$_mO@PDJ-ppz`j(Q##9+a z4wfhG*rnE24yPQ4-!yIU+~<+d+C@ zmwi3D1Os8Dd4!4ewtBb<#X%n#*xu1KNWXb3F7suYqZ6}R&PH1XFFAK) zv`n-bAZmnRfg5$-;c0&&!ZPh=X&)O1V>OR=?xp*K zYXVgwm|8wTA`I-kXM-G0lSwPm&jPvp($&Ozm#jgaTg#*GTYo)`qt-^Hg%DR2aBE}JL^V3dz2BFg{MNk(62BU@ zs1{Hi`Wo5FLZ>q_*keyJFU~7ZqQnB-87ECoMjR88Pu=Xlf|G6q_eT?DhEJbqy!hGJ zM4cTWwNz;K7^|*mO=4y*$p-1;w1hc$;ysg&>p)Yh;$6FHujeqb<*e>Yz@JYB%V6ET z-jp(+IJI!bRbxBuHJ?|dC5FZxyPpR7s7vjg!Ny=0h;#6VK;Ts^9++zex;)=Klrnyx z)dVzm)ws}9aA8`xk*Fz>l)qOuhI0$eAFSyJ!J`JoDLKb&H3rBy>7nXB(1Q6tPa>@4 z0f_GESBA#Mxca7q<7sx_MU`R+sM3rf8I7v8X1mS)1Ia%Cg_l|>OW+T-(CPLN2y(}+ z?;1ft`nA|d?USd2C=+-W&=a~}KwC^`Xc%yzyO7PkuGzkV!P;P_ zhuh}fA~MVWU3X7?1{8CR@c}Po!vpHx&GD%!hq!ZD>~Q2EuVa*IaTfO)18xD;2VLPV z$dm72R(a0KlYcG-ff;_pw}>Id)^wne<6NQv35Uk`8KJ_>yjxs`HVHHyKZ~;#Z`{W@ z)zoUXU8gpZwJ`lCpWYySanY6rfC>RhnDTI(+cvS9SHW%7 zj^36+3>#V;0NPi>nnbnf%dsTyCII3*V1x3EAN%^SfdbDG}Yz<(R;_0Y<&?5_f2;1^btvzljNusj^c%I!_y_boQ( zuG+(3TvgD&4Fv0qyD*qS@Ojm<1}?WIdr%gKKD*ZRbBprx3$PAsJI6YNV#S8>1?(#$hz@z?*90jFDoQ4-afvZdrsZ0wNVM6 z5LQ2Aid}YeT$(rNFz8rG@P6f%RUBB*GU17{Pp1#b0BbhsB4IEk-AFhLrn8I80)y>R zqk)gr{*{jniAOyw#MtGHowfMyDWYI7j(*#ByRK{+sJtvBr#7HeFvJFfwc?Jp4>;v) z%9M17@}q2k8SY6i3?Y^ArhIL@#6@I>VeYxy5z8*%HNClAx-ZwE%HQhcN+!xiYKJsV znxj5S4X1K@EFcv(w{J@gSUML4(G#9*^z-JT-BLor&&>ze%rV_1t^C2qjCY6@W#U<2 z-)CG5yDKCM-StpzcBIjh^@EpC(~6gsQSe1p{U*!lKK$MgpTjWN9R(5I4!T0L&K%~F z{k^ArU04yNnDVf$*5@7T`HxeT;)iG5;8)nChs zJ;iG!XImaY{8X_M1`9@i8WyHFIi6=0#W;ZiN}LOm)@o z6+>i#`d(f&HY~g$t z!*K&len7qZubafchs0t2Xsg0T&Pc6G5N3{eBQdr2^B{$&~y?Lfp&7t5T z!YY&tNzxCTXfqM5hJ|JdGYbI+zWN=mZ9p2lh{_7-MR z(oeN#B3{Yv=viF-+4eY{aAHHjE;u$*vYIyf6|;Q;R}h53?baH&1WnaE?wva=%%^-D z=O4#4vBNfLpvo_vh2P=(^t51IMMG5iUU>IzSgwH8yZTr?1ix2(EGB(CXH~ZzG zF6~_&xWUbH$Z8@`t6=FMxRv5uHwV~Y-eeoRWqWlWIPW^U|9`#!L|y!Z#|06U866N*Q9d1A2^aWGitaUxnjJ3BkY zytCTg)s;q$G3sK4d6y+&-wso$)TybjNBEl+QoK5UeYo(WgO86-daS#z4GI0<6vP^pP(CMLK3Bd*FPFC7vG%Uit-HIs zv&6UU&C*W8UeHj+x>vztdH(H9Bkb&_5xkdGgu0-h;5SlGS#e28#L~xJp1)c?fBsCP z6_q7deB>&?mbxvB1BWSHDd$1ig6F^7zqoi==qB`QPu`YX2_pOD#}wTyL^O*qLO6)x z!;_3P@TD}ti0l`Vu$WK6h$!H3y(vE7!U)5YMD$@{1m{ca%R~Rqc9Z;U+`#v+QZ}bY zJIiEyrHkX`Wy^x}yR?iI&1uhPLi1YsX%koXl35N5PL;{mStAGN{v|<$mD{QaTsc}p zS_5p76Lx=f&f1)Gqt@3y>DD&-fHkuhO-`UR-PBj)*Q4$9<%^{h_c&h}C21sLU#2J; zO}QJ`)3%og$otb5yD`BoBlE`YVh)8)q3MEqCa5C2FBM|9l_zGl^(UX&ddrm1A+~7g z+~Y^_QQms99UO#Fjl#-ZvtP#ui$r&q#xr+c(L!^4bw3dUKSWhoo0`AtytloyF*N7; z1Zk?6oy_9DtN5?u1|P7d2P~%YHd&u1?A^-gUr+x!!KQ3~PnVE1x}7uX2r-F}nESSF zA*)&EYHMDGaZ^BQ{%C*Z*M7*JcT1H0K@H6xy49Nuzm*z;KAaldMf}3?PCpRrN!PKM zIRbi%hK%UViyeyKOx&I2D8A-jhc*{=i@DnvmxU22o@9(P`B3ZyOMEDVJ1!zZTvPJh z@K2^loB*=%jKH@vnaiR>Sven;r<}_lcy()xmxcLeWjNzDbJ@1Iyo|189QG3R&5R)C zw-huVsrU#j!?kQIs}al2W!Gt;9Ya<6PrD>u(2Xvcmv2ow@a{GVD|BY%TfPZpsoT1@ zwCKZ!_fiK)^EJW#k)nuDwXqP9s1VF~O$D6fN$q$Om+=(J#Qf{GTXJ)iV;ud7G4SU# zMX1G1v>AgG>DqnYDc`f)I%l7WIrwItv+R_{qv7RcWr`>i!gRm}3 z-C)(Y@X=dL;ntfBXpu&TtYV3mBpmfzog(3p2BUAXb^0kM?@e$}`oTz#oJHyxIU?_j zK4qO9NFxo;u?D7JtA%!wTo-85VrjoaG_zMCx@(w%sWQ!G&ORBO9>~PSOUS$5M?T_< zXDftuTvRi!vYGO_l*u4!4*GP7#N?sk_dB{YDm!6$9=}S**1AaXt#)ovmboc+rLy(B zV1ghx%3|)PJ1hv4{W2Tzi17-%h>Rl(n){^OyC(J0+Zd4*RrXbbF@vi^v-W}^{h5ub zS6lt9BpOEZx|FG?J=d@KP!eN;cgGi>wH9i$3{4dbNn#Px9Ql}}6;`d!Z#l|lB+?K9 z?mut&%d9A}45BkmqaSMB*;!AonWKl+H)O{{n$%C-8ua-!wcB3U79H>qyC%|R zcQvSY)l;;e!afV%EuNGJ{L0ky>eOWhxKF=5SD*^5GkV4L=8YRG3r1@T^Q&k7cyv`F z)CBZvz7&XU&967)~wU!GBjZ~mvIpBh@4{^@C1 zORjR=|I{=!A)V!)Ms2T{lWIe8E%h>n>-k+BZnuSohE7aY-|FeySm@s)?QiU+e7oLVms7%*On)1s{Uf7Il3M^+7 z?wxn`T5`sFtrksA&7`+OF!+l^8J5bjjrvL4b9NB1)_Fv5wH3n2-g^e(MwF^vVlOt$ zq0QGqhINoIOu!zp$_Ek7D79OoX>!|RkB3N$dc3&)76d;QWvI)0F~sUC{-uC{+e^`O z%hoMv56;qL_W@Y`>^6yVJ6Wq#e~7XveSbGUH4-whDDBT(F?H?1ifqteUg5RCI-h`$Q zimehz44NE@P+$+LWEwme8l}J1D7Msfe9hxguItrb zpWN?Oi1ExAkwcMLLXx4$MdBue5$q2^S|gcal|UI<)ZF4u=!s^pG=QA`VItg7)Ghtv za6)e`?AM&jWE#HbDJoprS*#!=>=nB=1S6uy&!%-?AZ6RHCi+D5OJ~OmqiLiBl%o(6 z=-z{jg!bTEkHUg&wrJNQ?vsZdT6*iXN@L}4VR>2%olocY{IW9*tXaCtw2B89qbx4o z#gXW$juQ#^xq#4FTgbg)H9k_Ny^K+jc&F>|S6mIt{z2I#m7`k3U#l7>fl^O2qB>UKTKl!H-X=~EF1sMi|ivu*uJMdNSIsJCDa%8y4R-GqOrH z{R^Zy%vj!H7b3@NX&8%%lNOycY|S&>#yrxQQ<4UeHr*F#usCx{{<(eRLhdU^Pt zjZCP+$8guzg7_6YdZd2GPlRGaE;XZ-7Px*e{;;EQJipy*fJq$ui@11oWY6~LZQ()b zNz9A$bFt=o6&UFj5CsAaz7UYtDjhTJlAu&7cJ4?*;QFlZ$52kr4!;wpOm4DBJQE2w zDa5kIoRx5DF*vc3$NkW%*a0bu#P+%}&xDUC*nZ2%_cv%^ZM~eC*e#VDJnlUog%Mig z!{2T?z^6X|1hZ8}i@c#{*sv>4Sgx_z;e_b8p;V!lVW|=Ky{6sFi-2)%78zQ#!(vyK z7k+?9qj69^8rOf_(A<%l@wgidsb-YNm-@$P$d$L`advhFSphg=nY^b;u%i)qGrk8X8bRPHHHW0fOa~0RwuHBK zb_mW^4C5NC0WcE`kvqHdaeDHf&nz*>+I+2+OeUWoS0NsK&-_+`W(@?{tWL>DCMOY3 z?9@cFTZydX?bYS=9A|NHpTO7zOOHQ+mMGMu;w5YXb=%nk>fBy?trMm|tTZCq2ouq_fXlvqjxjvAy1GiCQ0m0X z73Ac?b5LuvhP4^^T4Vc>i0h?K*zhj_B2vpuIkc_wlUCEwgd(z&`9mc6%pV;a9KGt$t7nt@IjpiE zRbR$wr493P#SBYzh=d1Ho&r!*!JBeP!Ig5T?aT`hwS*$f9md(pT$KvWL_3KFbG?;% zN;)K$|K^?6i_HK&m)s>*@CC+Z$nMx{38315*8A3&7it|b!#ivpE zO8yHcl4OZWHzuIpIPl6z{&fp3&^FI!a|!Ge-xL(LOsm*(98FU)Ey{8wN!EEPR&x%2 zBO88M_jhAr2xV(cV$u`Y9c77o75z|Ad2eW2b&=bzP5JgNe(8aCRP6_-@C4zG(7HLV zuvB0A#c4~E@3(e|r)tUCg!3d~_w6#8jU82@7Cnl2STE1(mI!fcz9*~{?iL{KJ@dYk#dP)dB#m$I>_z8Im6#~IuG{h zfG9q#ZK<;=4RVSLAlQd*bF=5Us8*m@gwS7intJ3alT1Q`qpX!jsBs7!6oFw?nr@<_5g~H4)!#A5UOpqf~`MoR%w$y z+8*LonJL9%s|s*mK%;F_f3yv=51c28%32@Hu$3)2YnO|JPU5(+`W!o znP;d1O^ICCbbH!>YK&gW0K_qISP<0&(X8Wap-1jGm?uARQBnA$x*lnWXpnQjXu1%{ z1~CGF3)m2vxw1bGBt80oFw>k;a!zJ-wko6I^^jQ6Mb zZ2HC%`ytY20R)TCUP^yoy&f~wV#cZ1_;f12ukCa=A{bK)ZdLSx4Ucn22LG4by1YAt zDxX`CxT>ei^?_TbBr1DqH1&%%N4Hkb$!20B1x6A4F9@3YG=)gGsKyDMGWDLHiTI?8 z>~;XlfQ2rFnU+)5v75bq#-#JRbNvY#z-NINQ9C)mM28H)3W3KS=F7O1Y$c&qYQLOU z=ATWjw}blkQuYtkBrWmE=*aO{y&$p_*F!X@!^_k$tT$;7VCRui zj(#9o)*dX}+GD`JdL^nWXFbbZ?{7e>u!w{Y?blxNuJg+ozfCZH-?)XDU<=gxQ*33K z2P+IcK9*gyc8RmV$K~|7ZU@qz-w|xK%#^=s^(2FPU>Q{>+sQTou<*~0PmqIA_)(C4 z#*2g~0E7qZj};CnZshd7A&dz0W1d9VFgPw;KaZT>udXmmIGs*Es+};3cF79~;UEQq zbOZAH6$Y7oP6}SDD-8OQ^jZ7$laF~75)#spV???;xVX4DG*o@WbO-sMJV+QWI)X?I zn7@c8`T6+;)_q;9VqL~GYD$xrCJvzK>yJ>b{gN@my6a=}`a&cfc{{+{Q+R1l3>2nO zO<;#H`-&IXfzb1o2VA;N<(bbM_#y#c1KNzd4?nxw?F&=lG~*o?1y;M$_? zX16-@E8di@s`o`()9POW%bmK9ikGde9P3h{)rNwHlWgOYm-?5$L zEB7U?9r3L%D>|p?hn)o3NbWl@!x(WR%JVv(b5Zd9@k;AFO{m&UQ{Wf;xQ_zB3aeU%bU-4wJ(AH0#t}C3$aSxRKc0^RbaeAjBzEsle%eqHhhs&(8t*zPqX@tV~D;w3H zB$)L67+zky&*T@^13ea~HWkgd>u1Uv0Gki_5VgK%z^NQzwgyVShvvt3L6f0ynzvFax(j8ab@D}Z)}B9{CK3b#OcVPnn-TaeQx}m# zvsEBbdGcf`CPn70Zi=&)`rqCbhXWDaaNb8`WsZH&Tg)OF=m0Z>1J7#M7V8YtJu?PW z9Z2*g6JRgkBbZK@Id?Tg#z&Nw`9xeH%CRuwPaASoX@>K!uK%%+9uGLaPNyXoZR<8< zHTLQ{-f4Z%dc`Jq^w6rgg3aJz5cYIFU{g-i8Ql8P))wUnuN5vVUZk;2^MOsWJ4-U% zu*`DMVwIYZVVoLd7sN!r?FwmGp{e{Q99WD5imN%J!PZnLlZ~mbG+uKd{MiJi_%8y3 zoiiZ1CaerQiaSbXDdSq=Oannu-T>lug)buy&0g(_Aqnq24pw{I@a=6gIl?W_6WV6y zFsNs)4sC}00QLD~&p}@mpmAn=JF`f(>4SlNF7$)QWADSnKx5rv)|8)cQ;+#Qu9U2j zZ9zy9`&P*x&HFZnucv8m`N)w;J>=!tBgmDDZld)ji7i%#fu~)wTMrBWz`z}tXyBc$ z41^;rS|2_pSCvOP7yV@)Z<26&RVmc7VI8CA7?r<26P@=*l2Gs7Gey@Fk}bVfV@Fmg z9D5Igc`naS7oZOk-QdfHq4@-`68Yelq zW5)3>zT!8gGlVMjc+7d=IG8zxP~b-(%E{!AkG>);JjGw^{%*LJT+*1IDi;{Bq_(5( z)<19iz)EqeMnR^mZFe{ch+wLnrGq;KHv_pl9>A5Bd!mR6;SxDNQbFID7ix6`K$a^= z^4d8$rJ=5TD5r*$Q*+jq#ocLw+g2X3Ye1Cl_mO0DQ0pqjWV$($!BSK%b+7c`nKq>n zo4avkKMZTG7wSKZvka^)N#f&~UZn5nPxYm{+I!0a>ftL})SCi2r0H!l`u z;r1?DLA}t{!<7aOM&(5SUTQ`Z}C6^(nCc1seh>l{jyg!wjn{04hXK> zUY7D<*1hU+cx-=~oKBVg$$Ki+rpf1Wy&Tftm|A#AY_DAHRdoIQJe9ldx~r!rvhndf z$h3e++_dLX$s(bQ)AfNsND{~2*h61yfM3x|;@sqwNf3YuwIq00_yJ>{w(djR7awGcx|I?TAy&zG8G~t_$a~ti z+=hSrc(AtdL&$30DEY&N3|B-6bz0+BGW|DjDO6?8!yH2%+MTipXn8&UyW1OYPzNn_ zkvh%E$1hnAXv^F2u!%jSJPlv&M|{{(4N=ooBLYB@B#3Qt*9)vB4OFWO%5YL1`%3=U zgav=x+}vz!`>)m7^}$-F$SNr(o;87V|CP++)b~XSof3+0woHb|v*6YMmvm-+<`cf0 zV~{Cm$8%xRQ~qE&LF*Xe*eV=rE~?k!vd@ihYQ~7GL0E#*zhr+LYNI*h;k36^I72)T$O3( zp5k5a&2ehT^SZ9wAcO{la`b@w?Sw6hjFYcKLYJwEjO^JYchzZwP6fG!6Y33VVnejK z5oyAy`;qXn-PNP5oNja8R`!5A*(GRdCdbFCDO;{tY$mbYbJTQzwSUH-I;hd+I3TU1 z7WPKPY1E({IVsUN7O82rm@AxpEY+obSRe($BOMBttcV1Qp1!M>Y{@!Ia$9MUk|?v4 z(2V7k69cRl=2PJU(6g3Pj8=?}vGKOixH?U(|<5XIC- zQ7irM@};tAkm+bADC8Azy90E1blM*PqNABOz$h+;Zsd^frp)$N1!ko&AohHze9a?H zYJ7OOrdMl%w6O3Fw0%vdySvN#_|IPdai39FzETHiuG}!#DIco)Y}Z&{3dXzuXHdP|nj_7RIAAVXzFge?`D=_gWqCS|uB;rv7TNlJ)-I zS<7;4jnTKpXu+?}|M-euqv5?4znRGKhLeuKV2i<&rbq;16x~PfU3zP|QiWQn!moVB zk5VC1%Ndi_zgrotEq8c+E-Wwa@QDl`X~6&34fAF|@_CCkia{3lGK+Z9yB#R%FR^cr ztR6g zCMRItfE4JO2R?jt4z-pa35Rs^RzR+%LB@K`gTFFfb28ZBjj#+5>NLw&7jnFQ6nOri z_pKrEMKG8-;5ynPj%t5ccx^q)96azk67Yr#kk0$|L z9h4TmE8sTl1k(By5J|AKX3ybk^TYLVkOW_FJ{d`SXw-A*tk5+y8oii}iT{~d18Kb& zJF`^(08Pty7>SFB;Euz@zxC~8HQfEDsPykvz5bJ8+5eqx=7$8hksqRs$J~I(*SzehY?rwr0|=f6S?*Vzf6xn2&)%oB zm1n;?mzS&CHAOz?a@?dmpOk=>7LIG+d2u$qC&*dR{v>dpZ(|XUC))Lp!#$;!9qLG* zd{*vFHTCqwuk6>zbD0~i2RAVFsYevf<$Cs<#qovW5`58aP?vD69t-Uj@Zee5#xk?13V={+MxbpcTh8ay}de9N50r%m&^g z_;Te1ufPXrrZf{kc@eK`ry<-u_1tfl1c9mnB+Hg zZrXD(Dxge5nc`w5W!uuLfb2dWPk34l_v5sR?E+~D3s7L|%k?^}#K;H3iaWOT`MEV5 zNgQ5%h2pJzD;?$K&bgbaKwgj01Ofpt-)pPWYpZl{C*FtoxtrVrKx31B>h02b8ymOJ z>ihs#oZ3vy%ENrdBLxHmr*ME324Y36F$W1!xtYdiVIc^xHSMFep79QZVHB~vjIEkn zH7x)f0|4(kr&b$4wo}?)Ap1_lHFrqc@9@dkLbFnR&F;Rq^qM5+a`C7JNMinWqPxwk z5L?@c55|bxXrA{p(=oWIMasD_oR*(Yi>1_wEo@2G;psfDXzmaE-Ub6sA_XAi zR4kP#wA8l5!KWPn%8)YPFjh!Ci*e0@8 z&z{yfYZY?rgt)kVeATxyEXL3#Q{0xU|ED?*E9w#qd6TqWRb!D@BJrL{6#fSS-@l=) z8%mO^82*3F=P;Az^}?PmVML|Tr@d=QAVB{t=&?u~dHbT>WbBk%L-~9NP&R)n^>vCV z3`y~8n}iWS&1X6MdO|1$q6*$c;VjGXK8!j>s+iAu&Cs9=eNZ{5JrP$0oY;Fj^A8x7!NungXnJ01XGkM-xn@GWZViDzR2Jt^gk8 zc5`>3?9D|3((jNMUn}(d*R4%C-SeFSCG$l`=an>U2B~f6i2h9Lf9wuID}8a2r`_Ur zBliezsO|%5r-uy1;U;gIwdQy(9OplM!73;czAGOxE+!@>-SAA&%`Vb&l8r`~Sy+bb zM9*-XO9HW{udf`$hu$c44-iX1{guDw-orfAy}Fp&$4dws?on}Ty%%-_e)OMJ`h@1h zvoC!Aw(V}UBG=~6`F$pt=`seh`vD;)#6fA5p5P<1)IK5!jJtnY=^TP zhC`2Qlszzrvf*yE8>i^n`|TD`wjx8>oFk50J8zZ2teZidTCG? zp`;Gzs@*cl*g~(9B#*Yr+#u5ZMoIbTjr58IcG%!BV^{@0yV{`(FT>>B|BiPpy0Sst zc6LKW;T^KE(xT)=h5o4=4%WhypMz>_h1Gy0@03oZYy$B8KvM%{FxPSkc&DQ-5LX6Z zoM`M!lG5WJY@p#Uti;Te9D#FK1~Len6>R!yPss>-9f;Y zQK_9rxJUC{iQGNs#flV!GJNbsyi}$Q**vpX+FZWZR5;v_s=$ihDlIH3%G(la@9yqy zXLl#!$uG)rqlYwIdvwZ`@e~Mm(xMC1MWEP{w0!G+Bg;^AP+4d}f6n0z^fyfC z+}s?f_3LESoP$_PzI_}-b_qhhNdqK<`lhWH7y{aMgN5d5@0C@q&LgJrbf~%zVp}WP zZ+*bh>Sg*mS=p7=yYms*bK^@& zSl9M1=&rjIP>r;Ec5#xFpD!8r629(@z?BLB4|@K);1Q+*JazdBMI&zCPluL--4_S# zgO>nz39SXi(5Fk@{JUDx;#Qg4C$DgKXNn1x-D`&3Yth8({@m%`C6l!Ql&AhHdx-cU zaW7gO&jOS$F;~LJLKtz?lonPQyo_F?+{UATG{`A$SJmvhNJ%PLcgSx5uh>rvG}KtD zy^i!HEKZ~sdSPfHN;DYTUlRnD)5+lL7R<%_1ArnW6ZGH|43CHEsLpCENsArCPiF zHP90(8_>9&nT*P>y{X6O>~>yeL>E5b`XfhPZDJ)K3^AZ>Z(GCxig2$BkxTniBxhOT zlLM8jP4UE}JVvDwE8Tqw_&TNYAvdaJFLKufcFP&RzpUCHLuyx|ZFgM6k%@se(^s5R z6_Nm&xPz&xs_bcnUwZM#%Dur8dKqJhYTRTg#p~D&gz<^bkD$`EqDQvR(qeF}7&D48 zarjbkX{iDdiPWS6m3*!WvD)a=al6Uud#h$(U*URL%g!pgV8O15^MX6AL%8`JyQOOF zA&jSX;*LO?CCcgQsF0jFsiS_uLkrc=_7cCgGSauYSYY`;a8VDbUO?mj-%%gX&Za0_ z5!)w>sIrSkC(M^GxtE(n$lVnOWidcc6{S#%LIpVmf0cM!O|Y&Cjixoz|mKKNKQyHMMl)>}w;a z%5QQl7%gcR1?OKFn`%bLu*UUB)v~Z;z1fu$dSo`>R?$}#TE$KX_B7XXJ-gFH*3}2BJTz_ z&0SOwBeQ5gD|Kc`=j9b2%6=9vKcJF9<(E9GK2=$jN}mGfiH`p;(Df*|YokbOm<7+^_Uf{&n*s`+!F7xTm4whVL7g%|%}~@z`09AhD)ER|c*yv~#1{y3M8fZ?(1eq}8cE(TGBP?n z2})!^CIm8E2BWMjz5>+7)PfS5{YDIAqW%tT%eRUAkxWemR1V#zm&Qwbt#EF8997>E zq*=qSBWaq!y_m{WewP55q!5^Q05&f4xpsK!^1Umd=U%0FOyb3lAy*lHiZ z@E1YZ$;2jrKTLn{Bf`ST#xcDk4l56ZG}%Jq&v9)F)r=R3%9@g5jBKF<2_xKrTy`qf zewxK?vJA^=(LWom=GXld<0aw9W_NQdC<+YIR;6`#OHnDV+Ai36+$^W*xR0rfTn zmHO^jhD32#5mZcDO)9W1UtNCi6H8V+0wq%@SISQq36q!_8XAhT{*brDy9a9C4G5km zu!+aOsQ>KyfdAE(3OmcSg*ZO;nh`4!da;-_RX4UBk2j>uaBqCcJ1Z%FE={2ok+9-1 zqAR_WLU~;n0p1QN5jYMCL4<>j^C*c8n3#lZ(?*LG7&(pKmw9%e_Y9-+mb?(xuBxc5 zFL{&UgZ*O}e!+xl^dOq4m!E?TNHgGiJgT2`+4eA}e0#ZPJ6A z2h9}z^{SEa8fe7Xe93bG>0j+!!wNIEIZUt-5ul3SMYeF-2DK~sjLw;C1K7Jq`1mS# zM{B-QQ@8)>t58M`vk~-y1G@-eeGq$Uf2>>kiP(}xqqe-YOP^&i9PyB7^uFGQXq&n* zLv3Y3z_Tzd;oT+*=6w3<6&?!?reH)GRw6^jAMkYILfzTek7xz%8-TY4wTCKvdGh1stP45QPh}|Tp4%*PJX&I~A3tF?)|Qc2 z9&G@LYqovLm3aKy{Kg1#E@RuLi*;$}(WaHTMvj4+4H&z(2Tx4OJkq2(`d9XDC!Nzx;-Ej?mLqP!1eMG_j?Ix*t;TkT$HY{&ed!GG$EWF zvimO+-M|Bi|1?R^xqAG(V9O_S8Eho&*K+rA+qmYWl)>NodGuRVBNAH`)=Nu9n(q%n5|e99P)^k3IG|<1yqatzQma>VYq8NAeHB-~4UvqRuG(<9!B0 z@spW~qva*VzRcRb`p(uM!J8Bc{}hq>p5+8f&=RgWjOP5DX8{Wl}Oj; z-C`L{L9r8r*h9-DjWyPQ;++5}?S$6U5|p_Iz^e)nVyD2^p&oqPQ$*{HDe8${QPigM zp>B#lx+VAEpFMjvubF5L+0`{RnwXeKp$mN3bO(hVPKOF^`|isiY>C;KsngNXp<0dl zq$b$%GFa7)8E}GsG zl54HV$<4h>O`Vo&wOi$nrL?SmKdW#!4}hQJj5LO+0MTbQ=bZ#$YD<+43iD2aEr$#5 z-@m`iVc_B9d;~0YWjqtfVsy1HLjCn))_4ODbP=3fgn-G_5ePCtk>TNIyz^{9Sl%p@ zB7FXZoT5SmjQkTTBr-A*hXYCHAn?5ImaJDMq6n_j9^_KgWAXF5Q#n}x{DGQX6y#-$ z@2aB+q3SQlu0cg;E*ZF^-XIh=7K@ekL^zEHDdRcijg5^}RaM;R$K_JvSxiJxy(!mV45pPNLxBsp>}x5Dy9wQh0=q1-R$z4*)Lph*qbY={*xzr;E z(Ctsi{H`qMt37P9kbR5F8T4c3`;6kDEf7d)}3R3dSUU53o`C1!gf!JgfMIPs=3 z1BJMOMmU0d{M*kuf)m;s0CE0Kd>Cicxj+)HWSGP)zBw#Mr&IgXNyGD$=pi8fgGRC| z<(tjXi&`gnUf6=4uHDwZ8L;o&iiT}DVjC*-*RBe(p|3(`qh2Q9eC0)(k&2Sib86!=#Df~K<5;9jyjP|m5 zN4!@~vHa8D#=D(!Q{NhNp73@)T1Mtr)U|A^ka04*brA*TxV2d%wZ5XUzCL1O9lM=o zw!V;(nwnaD<(k64Q;q_r+whIVu-=JD?PM*JurkHb{N_+TUs2`eL1@(#J+gF!>jxxD zXZ(e49xSqJcq`r5b{{O^m96)lwCpf6qjul+vf<*5_2m}a>X=G9=9A-fGIITUW=O^5 zwoVS8e=M4~G_U=V^C&=%F{n1^tLFD zs9Is5P(gk-`f`pe>lU_%lK1WNA@N0N)TtDvwDCZOl`W;uCd$|9hd1O)1nTz3z*W0;I@;9D zJMLA=y3ddJ7;z6A>Ko|KjPo0;wY^laq2S!jPB{3&zdo_>$yFv`okr56`PA5JxhkaQ zb_Nvy4@$heRW$~}WM`#H6*v z%jfE0erz^;u|w9(9|mp%^#|>?p_(4~`U@uTg@5j(dJyPx8#7!|jsa61MS!=3LSc0u z+KdAZ9uTE$miY<}w9fi?dL28Q0BFVjZ}a*8jTrtrkbf}PRyu?1Z>NcsG2Vt$dckiBFIgAi(S`}qw z%J>~E=%`}FZxl$OcTi!mH>Oen_}4QaSK{whg69aB5k(!l>HQzTw4C`vt~Cg|^&BDC zvKSZ~ym)s-xH1XiARQEPUTiuQc)R`1vF4aH0Yuu6Txt=_lvcK^M`oY=(X_#l39Hrj z>~1TJUYzI(V_<7_&qMgofm*$1!6Cu$ok$W1wur>f`O6=ZA!UQTEs{pARx7* zuRU)56dJ{!x@b7_wa#ATBP~HGIbk}d)KNqQ@yew=iH+-dQVZ{Dl-m~+omsThQ7!)+r)}P&;W+t#Y&Y zE(L!ZSeRNmNC-Pv#zO^kEuQPa)9vwEvXqc0lV0ke8CH@z{c=ifq+eKFG-b&<{xmg} z`Ua$mKzW&p&*h-^9lrex|MaW(N4e@PVVG=$k&YyT8RE`j9;UwH}IB=bz4UNcq%hHF0RL8`=cb- zd-!kq1wjMS+yiBPIiWPrPxS?u035$O8G!xb!SHYf_YUeR3^uHgeO+7cjbR4G1eZwsFt)`Ao%hs@WM91vD*CZ&V<9h|M{ z_r^%<&i%Z^g2}qVw*XK1HNgQa>W#=$spBmNAgvwOX6Vo{r)a1+2#Ea^Bg}H~eg#V< ziLBCD)Pa6pk=ImR9CqgTlPiUQt;T1|XZjUgCsA+Gid-n)W=>y1Z8u35(|8`_uO=-p zOrkg)u)VrJ&mk0Fb4_rvb`HRNs`#~FmTVo5^=mA{7Y^2|%UBkpl)t_ZI$~rVGmBpeQFyS z85tV77%p|xpOHa{jahh822s|xc1Tq|Oi8i4PJL_(kyC80RFEWEs;v_BNnTVOX=rJY z<>Uak^&HX-D~MPJ3wGe=yG7)jJd_2|$V*LGSy?oL&`coMd6Rk|z74g=$+H$&-VH=c zggw^xG=h6)rKEs>u-s5XhH$04oRy4OO$FiikaL91`$cE_Zz$NPdz8jb%OrG{XS^ zAdkN+8c5!INW?peoI2iFK4)cR#i}+Dm9C5Ax5$7L5gslcBw*JvD33=(6{qJRIiCz6 z9kxiKLI*(Bwr`I_b1V;R6gN!P_v{c2tGo%fvCd-sEIoK!G%>vmKhipMOu!YR`SVQZ zhJtD(h>jskWo6|U!8BgqGX?7P8yQw!e!d((wYTXjMDa^Fe!K_wBn0-sb;}(ca!ZJ5Y(O6Z<_qZq9M_PsF{( zQvflA9}QI&K$U@z|3tIZw~()TBQCJwT@Q;e<^u5Fpv{K_6*i8wYmv3Vo|e}tWD1YWBxr0>96%Zk6mjWNu2EsvAR8|+8l4WN@22*8l- zk$pF_z2mdj#+_%md8pUd!Z1VYl=L^zq3)X6)aPPb1}jm*Y6BJY7wX6_ctTu?F0HE3 zn8T-}7sZ4^FD#!!um{Z?O3KCQTXi4}^mi>g-$&QN6leN)g__XoM3#gwBx3KVgX!o` z_iH8n^@waEY^Pe&ZX+WOe@6wM^uaGRb&(YJ+=L%c^Fbg_jQF*js@b9%tgL(_@6>R~ z3e2mNCSia;FIH(n7vj*HNBxC2!$W(=hOb~2r7kd*59U~peTDg6{RpI+Wxs4tmp7ar zK6x>oq|_Lc_FXOJb;E3iup;36=ePIYKi9e^ACmVzqT|MPM#LE##vHTP-}->2i+dw; zC_N#?e#W%+I^;&V!Z@a$urS4|xmxU33ZL+$05q3)VqjQwQ=H-4IJoIXW5vTwQ5WdP`UEq~Yp#QVcN`e?TifviuVMm9LT_3N-@<*bQh?*5y6vZlIFp+t z@pL*rrYQ7r_p=Jw_P6~hG^~_NHpam7`f~Svnr!vLP=KjL@zDj1GB*ZpEh#t3C3~k- zGA&nq%V8DjQgOpoWNzj%iT2XTpqM{6?Yv-gVFB*MKJ4!vN)Hr6PB*2BSvKyzpX(BJ zBRW(OnvzMa=M-0v=Z9$$Jo)8#6zmi69o9y(UApNrYk_dFOx)jvk&99)8k3>xM~hXK z%?;UFLeEddzU@_XmUtl{SSkU$OlG=vl!Df;MuS*N=+n~ib zMe}7mE{;@XCxmjMxF5e%Y2JY5!1;Vznp_b~_Dg+eg=8psh8E2^Mo=sIE9btHZuINR zQX>XgoZByo3_ibgHRgPM`(-XSB?jZMcGNnKTv0tOUdRh>Y%VKTGHv$64mbqduW>w3 za}8SP??Cy;9@kDH;Dzr1n;+uLE*(2pZcZf85NGhoeks&Cq}a%{pJb>(k&0pH+$*bN z4j;Z$orRXS#LQ|?MliRiWHh)eF}rm~#x_jInUX^J0Kr!N;btr?Wv zOd@s#9o;Ntg&@Feo!L zLJ>M^m@%3OAz_?joX6~Ys^@)wdtdLn_rBiu+JEh?t82`Bzu)^_Yu)#~)@Oaz`ldh~ zZ6(AM#Q6C5BKN>b?^K^f$R7^z?Quos%)l4@KyPG3@Xy?VRZJ6!%Jzl;Pm3(@CpUffWOVx*}lMbir8njT7#kR<0E^JOV zsrKL6f5u?*JFcGvv)QGwm^J+%f0{MT`g>;YHh43E5cYxT)46bBhV`M2kME2=zijV0 z6^r=i_4Ui5*LJy;-)$g1*oJ#yyf!=7YBCTzY|5AHTtaq}=G`Z#b!$6DY*LqB_VrDO zP?S7IEYJ$e-;f3oI9fZ2@7#`iF%AAs7lECL-j0LV2x?U~h`@HMfyaG*KTfC= zrH+mU$LY-sG)HsZve|4JjaKSZ;GLl4a49AxCL-eTVry&bn>TOhehJ9j_RG=HrQM6d zU7uNs&z?OSk7xJ0UuS_udCb+T=liB5B_%7u zV`GmvcaSv zq8vOej~Zwqwg+bUp_OUJA~$+y$Kqlt)6&H0o_oP#M;_VyocT0X%V)hPzi_CpAzDoc zuRN1qP~a1Mr{k5)Y8Cd%yh?G@R@jtmyO-x8-Bu$e<=&sbX7qbPc>Z$<2?J#Ii+VD- z>nT>50*ghXFVRws_gz?kd$mGn`Vu`Q-QC?xrdRodwb`LVv&Sx7y}I)KLwT{wosjCh zYf%xjs0UC#S)8f4Q6YqOy3$SiLsWeH#_a4F>$bajIZb{>Rs#)4#2pU%uXsI5Nmb{c zU`3}HPav{wx9?rqKeF1>@&f8LQBP!ldkmZHJmook7vAFrU3u;7srhEo;AG@fVO6~A za-dvEQl?@_whh_MOq|-$VViVIQhqc3q+y`u3>f7+^UWU zZ+BFNdCB3#HpjUZ(!K~M@39g`@32nYv=+B331fWTwmdCMvy$!4nVfuYAw()p8dLqT zynJP9KHx-fsD#q-xw5}G;gJV6%3$lR6_nQw0!G6VYUaL$%DPxgvvz?gRdr(4!cE4!b;SpqH|`j`Y};nMvAIw)<#JTi z_oXi9bGf>z6~^NrpBNusUzQNX7ZI}g zo#KbGBhc!k22BB(gIcK?V2-+iL#c~h$B0EN28C|DuedrQFZH%vHv+GJR>t{WY+?5& zRYS<&W3omqxm3DmJ3B5ZmnD3AvMS4%eI-Szs#9(^Pjv?jBZ*%J-I9Czww-sdrT-9t zwg#DRI_h+tmcG`%_=5kYEBQY>zF2K>?sMN#GnbRFd?VqanZS-@h!ClRS%=co z)%Es_!a_JJoe9%XoAtL~#4cf1=ZE%VcT zW^}}HEdR+aHE6^*RrB;o($(>4p@!1dj8ZTkOa&i}n^ z7X*AdRNeP?;et#C__(3#PztV(WLHRVuiC5e7wIbN=Z#*(3FMaSGf0`0=?4={aplHI zUPXV66X@R+@blBp()mYh#@Q#`fj&4@I`^7-p5v$(DH0-BKn@^ zNozlV_d%V-3WgTprY`xJ=~UDbgQkv@_&UAchn%N^=<_cl{pcf+%eIOuHtqNKVvxuE zr7};Uh&GBqRp(VnpUX@9Nz1p7V{jfbYno`>shR_kUYp3$_^S{K=5+QBW_{FCM+i{I-5g1?h zZm59~f20V%tfm|$wQM`iavKg(BLX{>0Z{^>B-I)lfDmMD6V!t0@XNZYL2rQb7qA_d z!`Q>mc6f33EpQBNd!Poy9|A^Vl)?jd|EEVPgoIfj#(>D#+BVW%>V!XX%6Z#T^7dc{TD#jh0S(+J`nVCV6zdS4` z2(>jLR8^I(1iu1D3xwXI2^$xDj3OjgqbeHMa!ZMxGC+-uQVsHi9a7Dz+T41K6<&D;Fk+*~G;Ip!o7(#>WQ zqv-AuA_8#d;N102*UG|L65-y#;s;tivg+i`6CS|RGs35wEcb7p`qr8nT>4lo*>&6t zI`Z`^#4i&6L zhA6&Db+gKQ_)znGHny;KzO3x!U~BoF4^ajRWph1lJ~fCbW4QuTiQ?hm;i9S?d8A0A zQpQGYhNGJOK%45X#oT`sDtn@%qXS`!Q4q>)u^SIUT9@$C7=^JvFbX}gh4J!8F#-56 zQeK)6p86)!3D;AtwwgM0(6ny$#;fDl=|eo54++5iWMkf*Y&*3Bm#SWjC4Si0Xfl@s zSjDz^Tj0D^S=kM`397$$Ye+W+F9^q_6*AgOlTvW=u$!x?j;H2(*9%=U;*)KE4`(dM z`uzFtODD?HmmzSSBn)1-qp{I^%?{7y2A(p75{nq)5F^voAhwtDV7MX}=Ox+_`v-|| zPNcOd6VeyXTT`S6bz&m)9Yr5nrPXt9Z7qiTxvcBt-w34hwa-W1lDfNHwNuTbJ-rUD zk(N~&QuEQR36jTSR>qKP%O>_#jjD$ZAFd&NJb2_*uPd<>^|lmMdw!n?RaFFr^>`-< zi^*{%cqET+iU24pe;*rORyO9+8b7a@uCmsqvWE4@ot*b~9@EN)yW41eYdJ(cUgDro zbmN3IHi5r~RdT(*uWww_^d5;(WtMW>y|bPzY@bw^_n312#<6Ju--8o3DKmQ~8mgbd zE2MB{z@w)Uzd~qF3cYLEto>x2S@t=9BD5c7XR=k0T8r6ssoHI&4uuAVse7QC%E%cD zFc}HCW_Ux0mJ)r@h0ZGUH${7F|9~3Zc@7U?mbG1(Chh!*;|6lPL|1zZMW~~|uPcNQ-8HdE7(P-`l zXK-*Z*94`&b?eMj`{ial&tg}1$r@434C_Z=+^9EM5HQI z5##|px8;CYtxH&|yH{juYfGooGenPJjX|pL(`8k0SF4(@`X}sZ+Kyp_bVK5j( zH6Baf`Ql>2kG%;)VU-#{$wl`BwtK?HXhM@`W&FzhgcW-H6rHh=Y5Maa4oF$_;^)Na zoAghaYKy{7ec*0k&umQ3#Dj;}yt$Va7Z=!DH@Uz}@76pmO0^L?5wp|mS89`8JeQDbklG7;3pnSa z`h#i%gTIoTAUi>PX<%b>bF|VH;D13nqXZ6peSOqoFLW;mWIH3ps3s_H zfgMbqfKs?S05<}-k(~s|llqxf73v7GvVRY%3N5X@j=`f=IBQD<770N>#>(F7uhe%s~zZ?C|XfpFMYcpHGZ@3 z&NGmBOe~If?`3`)zgr{S-J`Uw!u&OPm*i&r&@u4`J#lpIA`_T}h8Qu;Q&Lg!Iuqj8 znC`ZVHauW87K~gJvPgWmTQl^ox_40iiMI^Fl#%$F_!@ICT4u zEOe@1WQRC)_GwV@yIa>N&JnM!Ul*{j>wwTCiW|LymCSD=UT!T2nZovD^21TKi;IiY zPgjfzI}6~uesFXF0D7_w=gRm1p+!%fwd?e?zo`$MnVvR;EWqT|UjbvRtUPNE)#LtE zC4}dEg?2_Em}jOGk3tcCN`}u#Q;-MtDTL47#5{*$%jFISi)Ukj0N>|tXVVh4Xq%=w zzTYTwJiS&FFr~PE*)&+C=7D{MuIZ*VZ+BaYYDN9KUkh+s?p5CwSljI`>nTkrao>6b z?C|J8_}`BRZPoc^k&hT#819h`A#isuwdP4^%oT|$TpBaVoDJ=~jOP<^~o@QdP z(%O36!X!?@i8=NO#MAHTo4v4%8OzV1#VGG*m=`cE+5cxX7seu=7Pj~avl#y}R)d3UZ!L6>*JAWCrEA@FU2GN}MI9R8x zbSuo~3Z+xw?yjSI3k$ZBI9uSzH5r%`M(gb##l+N&!+IZ_ieH-Uj1zAvw2RP*Q?r?x zJ?ym}U30G_LoQYv_AVxOfTh}auv(>r7v_Re@yda9>Wfe=xYSWT}te&1W zfA}eiPG9vkwOWYX7sc?$+D9ZWHX7z%$0_%n&Jg}#c-1hsy?jpw263V4)wL-b;30s^ zi_(W;=6)OfC(mSkT7f<@ z$$~84K{*HUgsi52_uQ8jhK7y{WM*bAu+OsVj_QLb3ka@49X3Sb^1|vWgS6UglLBA{ zkIo93!!UA+lray4e%~~(*1xo|oW-r*Z`(Mqk~ctc3(`tnrewu0IB^%8rj3L^l9~Es za%P6xrN`--o12@OLNfiLvImwk2B1T%!?Kour`l-qTThB{*tEqGOp7+=u*$2lOUh~X zgZQe9H+cO|0{14cdPjfo_%>%b?m?JyCP`iU-(~Q}qS=AwM~`YiZ-6Mxizmef&_?~! z1^M~jvT?tScv}+o?H5(|uNDDD-Un@7Wod)x`Mx1~#=BhfXVT&7g56jswTJ|9@$u8! zKOx8e{c7CiH{!&k@R8MkwEw*Y`+u+p{wqU<3b4V-4Gj&AjotjBl=*8f-XlSXyJ&9K z;~>XqieF!*AT9lV?@cR=!U%34;?kw#SV`MoyD&`%;gyLNM9BSv3Eoz%zg=otY9#Gq zOK#n2WK)xBgSH*=E&D@=_3|Z#Df~iTQ0r|Wo3oU_T>}5y%V|?nQ}gprnX`;nS>G;wNo~yJg5Xc$4eoSRdi4eGX=uwXVI{ zhRg9>IBAD`V~^DUNhJoLv;AT)J$p9^H7N7<50(3&<|liiXZqt-7v9{RRRD4g&NI`GrG)qC&rLC@%ro_H!Gxg3ZU92IQ{5YGPJDbJvR? z833q}m%D=P`v2RI_lrD-v&&ux0u*vIZZ%L|d39VF=j7yM0g$gQ-?!OTm5on;G`ONa zg(7-R&CFO>STr2fzdMat9c;bfw>~6K5IB=lu>Nf?0Wb$sc8BqX0Ez?f7p;CqOHqjR zo4i+r+J?u(l<$RAy3O=AUIy0$we-dLBW3JegIJ@T1zRO0m#Om7!2YMV;Z{D6Hr^{L zEiH{@rKJEeMMs3XJ~{6jI$x$&0#^0uZs`2e&X~#%rA;}?fEf7`@R<_fPkM<8kMe&HYPj885AptQUPXVF}KWAR5fpq*OtOA+|JEa zWG=B-Z;?Ab0M9J>*u9@!&K2`>MBnM2c6>+a>&sJ`D;qL?{z>2kKsOU-cJTik&*uIC zFu{R7_fc!W%to0VJ{+EhYHn<5il6`PV1BS`eX2~U^>ces((%!KnY zXwH@zFK3uO?EhR)P{7mxxTboT_9sz<`Y@u#jr$_zdL3$jeC);RsJ&1L@KS3 zH14O}Wr-KUM?KVlM!rf*OB)_OORw6ntnV?k@0iY_ppUf_K*p2s!dk#XceJ?f`~JiX z0C(5zxY!?kbNoiD&W@bDW_{x~(F#39gFq=bSs33{JDlL{jP3vOrQXpjCb8|JAj?Ap z_I~8#!|7941)_?I%3UXatk&LIyQ~ngN18PlG5mrwT1Y zZnyvSz`^$F+G1tNrDFMvQ7p>a*4>@`^y$H=VgvLyw#qS+>0)=A&LOmbf9|UU+b82E z-4F3c>W~k#cuD4@@Ao3yd0ZYbj==}@DQoXHj>RHqZm{KoQUtB%&oCrKY9=Aq?oMwd zUa3_@lhx*Y!NV)Jp|312i`Q;%r2=mE?#l-8w63TbN>;fb6bJGJX*+b z5KtAz33E59OjpoYQr`8=Op4KqCI^QJ3wYRVbb=Bgr(;tlY@wE(`hdx|}&~|Y3O9|(mj`&VlVYTGr&fHW| ze<_U5$4}|8*3u~@vtJhC#&>y_c5y7iPTc6u6=;OA{l+SV5ktGy&%~`oeKg$}T02#2 zY0|_v*L|PBTe3o6jZ;fT?(XAVfN~+e)&Bc}&msoDUVW3DUA1`d&^W3emxfe6*XkKD2ycQz&L@R-YDYP+D&u37CT2tG1=|wNO>KWO-Za0+urR)@%5Kn6p#>-9X z8?i+u5(G{l)r)B(KYnxx<5koa)9QQNoXftNd_G%Dyz4aRv|-q8Tg9lO4Oo*1ppK-u z9QVy*eOVxd>u{!sU{TA(1OZ4KFc|!NQG)z24UN_KsJb18j5*z>CAAqbRP3b*Hl3i> zcbAdzMPdBCVUT+Fy58zNUUAJC%UIPF(=vaKI3}O5rN}yW;ZU)xUzQcRvUVu6Jo&ux zNcndPS!F7q^W_6?0jgWiYNaVo!`Xdrk+4z00YUgG{-;S=P#V>kDy}sjMy(npdhVugmP`4p!~!uEe5 z8EO|VzpXb-~|MpX+iA*`1t?UkFR&)P`-dkR+R9S;#7TwhF9P2f32+F=uw3l$O8)AIv-Lw8qo3h4=835R0-sM`Me}Ru^WV8S)skR z5W~@hsTqH@hxybJYbKttCdk?u*C1`)yqk+G9=X-9wcdM|OGO4vT|2>Cc9{4K5J_4W zjGoWQtEg4sjM;L3=y8Xl1oYp_U=R}B>Ya>5B-PlT*@PT^ss=T<-_X!-Cky~Cz&vpo zQ=8A^R7${{nU{;{*2Bi%Kr#{=`%OF$7JyA%l{Di08g=_9rfAnq{V)|2H0!r@q`YsUw z&9eY{e7h63GeaQ~Q2owFL281lhbXPR3_kz>9}g|ct|pR&z@1L+;}+a`iw00m($&-R z0mz)8f=T@`uEiO5N??Hsy|@M=;XSSFta6#xnt8TGfpCJz!hH7MWjb(8759C&D8_<_ zzdi8KqXd`TMaMAsyo?F=SYDARoFh;03@^5ar7-;I9+dj7iNbJ2&-OI!pca>;AK`cT zcNSlM?AlH(#SM)&1Q_mS*#}%>G%5C|v+Ov5q!z7rG5R=+rmXg1vbvCs! z6*?7{in~2+KlFz&L&lB4c=YO9YYpsCtamZQX8hE6wh4P*p}kjKzrMc-Lk5o$+nY{G z_8D+Y-CP5naE-5uT^R)azhXTJ zwWc4#D%|C*+}W*_aaXTCtE;QSI>k*jKN-cV?TGxLQ{Mx2ive^+T(EtfP51Nq^KHS# zcmeA?EwaD4xv44Yy4;@Uw>#?bMy25#mv9TPzyTt4$8VM4THsFQgr^Wn(2*{<&&G$A z4_|=e+AYpc1i>kHJC5&3?+^seOw)2^*2lNq^`&YDs5y9uDynKfz)2Bf#-1sHPL5k` zq|J!?XfLlWpYw`Xn_g0KA~MBzCCp>sL}%Z3sf`^8Q3KqKB@oiROZh{nBvE8zH4@?Rk5{K2mi5LpxD@fYGX@JhhdF|S#f2Skc88-sEJ z?5%|m=Ru}yCWLU_>6V?2L1dURsid<-t39MXvmVP7hd$n2f(U+$XMMYwTboYwCEen@ z&MP9+L{$ufC(xw~ceM*%mMx?|jM;bmQvn$xD#&^sVM*${L$dR>_~fQS7UvhL`=4{IrCKR{bo^mbzNN^N;Gz|)fh83HpjB5OV? z?v=F~RQg_1&ilv_y~%j+w+I!)Hu2+F4IQ)rB?#r6a9q4$K!hsDZ={#tw3=)eQMuji zIJ+=IhMw>N8Twh_(y(tm>)rNBO*cc{p^Q{3TI>Rn>S%CuCfj#IrR#;Ch_|Yp`m1{X zU`{nsqRQ7GgI(QAI{SF;rvI;A0vl^T)UN77z!YhA7UB&CV6thb>BvTO zBQlV|xEfnm8OEAFaWy_Xi(Y)J=H!*lxTNGYVn*e zQ4oxNI(016+_6Hl37Jtnak}j?ZIK*K^E6l8g#ym3O>1aXPpWPICyppwt<^%P2tEc{ zt0Gss)P@5)J4~<}oYgJQEn;nfRw45tGkyest? zk5@-Vip$-kVni{fJAcX$w=|u%*~7~u{Q#(po4sxJq3!6?>XCE6O)#guGIp|O^e%y! zkuo@YXdF>TCZ_uW%;M-#H_Fj8msWoGoeA>@qi^Dkqmr)B2|LbIWPtpKvdgp1l_Jf} z&2>?$kOMJTau(V*q4%F|7?gCz`AIZkl{{^~@~t2oM)vRt6(k!-VeobFTy-RvK?oH zIqWi>0TCj1S3b~&w&La&s5l3LtMkW|PMiX75TQzqWh$+ed_+6 zSNM6RYjX0BHg@!F{*qy77G$tWFgm+eeXip3Fa-HSS7RDcp7b}oFd4>d@GTC5zJrx0 zjMcle-Tm>#Vi;Es{3GhNPmxQTwX2lA3z6e;lVRaL``_l5oQCyCDOzMVp-6r39#p zebs|Zsh&zzeR&62ABU=m0+@r+6vpknNt;uhMiNS6QEz<70Yeh8*L*(jL(4#LrL_`A@{?j35 zvUcz&QH6ccv;l{P#>TuQ?zX(mOAyr_8~5M%J&@6ULtTJS!x~Hw0d-+{rWCkcqYr0i7RMrch3w}0Y-PTSxU!DUZ zq9$SBKr?DB85QI9#i*|UdiUZYD%!$5VF4!ou9rLeIhz}JzDQ`lhP6+tc*A{TG3u;J zZEZrryGW7@Ml7Pv8Jo=YoM~&bUdS3bSC@-n=qapC8Qt~~g*6sY)0CU4Cg-xmHNNFl zs_@H>5u&l6C;7a=PNUhVKcExGJRA)dpK4?9xg8rg4uH;+(q|-~O`s9Mdd37mZa_q$ z!on7e*69RVPn+mvXU7~^c+7*w8-+eUc2ZKGp=cDGm-4J*{H&6K%Ke+=XtUAK!`yNye;*C zeH-Y+Q92=^WZk{Gv=q9Pnhco=&K02P9&q-$?|B8ox&&(@97!r5Vgz?k% zX@-4xautVB_%{Jc95fbj`qKploy<7-27!!ITO19mC^zcp?~XnU z&8?A_u0*N2$BDwUQ$dCX_dehE8fT74k-U?pYtLKhI4s!(Vsf3}7*n^SEAqlpO3hLZ zV(j>WL0O|rOph`0>9}$=h|hV++$=mnG7#xk>xHWc%OLU~THozP0UFoHr1(M4PVKjV zbWRx1@r1139+AJbpxf>yKrhpjEwDh$oV(fgWBwohnLrQyakrEp5F zZSEHqpkx~QG5CtEsqv%)t%>ZrqK-vMEhD(@T&<3huc5t& z)H2SRc%De!@5Y7@d2^M#fMj^|S^0E(>|$=Yu`6H_LW?2m^H1$vM~u1j2vtT6JMt4_F?$88iz&u&b7I4oYu%~TZR=sE~JR!B9edsMg- z$8f%%mppzOj%AGC{N)IRN=8o`y-szOyabp-&4>mHb;?ofeCN`~Zvn%+xxA9gTE&yJ z6nZ@Bwnp*FThkG(EV;{hQREKx!%|z94Eo!PQBiV7_ocSDi2vDyC=a{1Mig}tzqu$e z;BhiQUdg&P%}v0l#lh3b&?7B(kL$bafye%0XYw99o{~oF|Kb1eXkB880I^>`bV7sm zpna(K+@WvV$dA3X?dYzNr;Wep%VB(FFgDgmu>n;UnvGhp5{RIIm|;xgG)4K1S6rx0 zlo)PkqKuH_`H2}}m8Yk5vnz)4Wc!B+up&iouU1(#st1Z$Z2B>}P^9)wildioj3-gH zHPv_Z3*!_iCvmBSsNN@AesiMvgiNWy_{-#p9k|cqb5w5oGhJvTJF}BKvKz`gmEf23 z-JHB{aF@NSQ%O?S^)h8kpS{umR*O&x3vx4-)}zn_MGyXIO!}p^tb*XhBWh4J=60Ot z{n|ZtOWclH@t?O&y)?h&ya>rt!YF)xu$O93owHzx4cj`6u@RFRUX}H$N%rvZ<|dW9 zd6!AS3!{3CK$5UP4*8ONZ*ItbqMq{dN~o7}MTqw}`^9jgav&%V zUr8Z@c4uB-+&3~beG}sFRrv(2YIr;;zG#m9(iiPoPeca7P>SE#`L=hfcSy|kkqms= z<$nde(odm{61=E)3+mUyL+(uAp zG?1t~man}ZD#|VP=T=MGE z(CFys#bAHKOZOB(KQmc-R22S>0p1`2Il%#V=*|AW8YJd-KFNWhYMU-{QmZ^HD|89m z7PvM6mZFt0g&TVYv^cM`c<(Yn^t~(&y-*troriJYM)WfNNbo|-x+NYUC(LxJ7`3RV zXga|Q$=@n}2MvX%EczHIY>QMkfFK7Xcn#%XTag?Z4_JMCrlIeSWz{drJ7qkX|Mtx) z3s0iuLo3Zei^!Ox$)&@*YOOGRU+W1B%kypoKvb;j#qSa`tm$u6N4=$Uw4qg1Rni5Z z=kUc406j^(M(Yp-9cKdtR9|%n>#pjhk4Bhh{A|#F`St4yi`(|g?rWm3GvQzz_zR$x z8MzFNEfZ`d#ZuP(U&D>CSggs(Nl;Vp;K*rFKr+iizOAG}D%XrZOxSk}=94$CB-Ch<(-GS4Ovbsv>+o-P;q z^jTzy%Zg8OJi@Lz*VKeEv`T!pYo|`sy`Nz=4Knj(h2I{07x-O*3hGmkXtC>L;_VOv-#t2t5-4$B;5A@s&qyz%PI;+7P-%K-? z*sl^pvxu($>ky;f*@#d}-CbDHOmgIDulph0phH$#t~O^3uRGe}+bdziBUgg(1G8=h zgzRt0Zr6*F-6bNt%Ul4f9K8$k;8Tpj-y8h78#hJ88$kJ45Nw=Gh{IT2&hi<>eS>dB zKZ2I)McxX4HOF8~rTC2w0yV+z2h$k)oRW!rR2_nx>%*zi7H8@aNWV@vGk9CwBPq8Q z2R9SKLJQo4db#ddx&n^N8Q^ljX)55Z6c7rS&D^zSZb!oUjfr&dZVuTMy8*5@PJCMg zeI^N9wjY@Jgay97a5mU9->_i24?9$0Vp|)~S~N#M;7mx5dV=1^MF{Ua4gj#a%=Z4jxvI?w4Nv+!_Df zGZ!}s^@2uL*fK~x6H23~@}+yha(pi`%R5{;_(IEn|Gbs=T1f4)jTnBuue2gf{Bl?a z`Y|%Ju|IrcS~`k)*@TbpID40vHexNz<9;=>=bmmuu0!;Nauj|vjE`@JI`lQq3&{FR zSjSxp=aj(GSUqeW19}(d^7H+VPnKNsO?=lt*@f@cCX5&#WHWemF`xS;6}4mHH}wn{ zQW0$)`}pp?Z(*2sGl*Tr*Ocq8UUO`zPH`y>zk|wYN5`dCQ5Cy-GZjFjpTvWBr1Zju zcT3@8(S{6Fs`1g9v%^R7Ny!4SW{8T)TyXmMKW#OU`t+s*ldX*M=2|xftbe_D4P~1F zSVJ%M3j$*qilSqG*yj;3RO6=b>eFUUXL(Q3)r~ieWr9mqWy9C^+GBB{QfH})AfQHO z=()A}Idt^`N(7WQ0$~>_1VUOR1R?^)rP|UX&E4Y$!RbQ(-SITc=$jeo&3qe9HN)C& zMxA9NTLaQFzQ^IMe0ksO?}sQK7w=X0^8N+dPq{~nV3D3%K4i~#FKcZl-?c5^{S>|f vyP=!-UW2{Ew_AW;_CNXYWfNzSyUFgrn>43a3QOPxSUx*zM=QedGk^XMD(qq@ literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Outer Graph 1.png b/pic/PNG/ENG/Outer Graph 1.png new file mode 100644 index 0000000000000000000000000000000000000000..68837ca750a1a045dfc794a13ab91820a715831e GIT binary patch literal 8897 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 literal 0 HcmV?d00001 diff --git a/pic/PNG/ENG/Outer Graph 4.png b/pic/PNG/ENG/Outer Graph 4.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd3456878b4635d38eb708dea97d4693c3be417 GIT binary patch literal 5739 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 Ecl^0K%m4rY literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/内部图1.vsdx b/pic/UML/CHS/内部图1.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..8217b1516cc96316f3ab6e85000a7014e64db09c GIT binary patch literal 26810 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 UH~2?&A2g6Th*u9r^FNmU59jTBL;wH) literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/内部图3.vsdx b/pic/UML/CHS/内部图3.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..48c0dda63cdb29ad6a2f67b7f2ad1fb005d5b65f GIT binary patch literal 25540 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 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/内部图4.vsdx b/pic/UML/CHS/内部图4.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..69d890b3ded5a33906e19295b25d38e9427d6870 GIT binary patch literal 25792 zcmeFX^OGoTlP%h|ZQFM5wr$(C?cQzM?%r+Nwr$(y-QUc;-<=cl&iMz_ zRkbo#t$gIAfI(0IzyKfs000O9EMxZ?y#N6KCP4uJkO3fow1n(zolR_=^^`sAO`LS- z+-r5-zZr1c|7hnI#{ z#fBwa^Cv%;yPC3ZuiIr-w$e-RfO!6`ICGMhMjr(lO`Yrz0s868Y>D|}$eb6XdlTST z2z(kBh7lAMN-tk0f?L1B`n}Bss1kqa(LrAzNu;t^^Ux{?Z;7+$D>qnKMQR2pCzh&t z$vL5=21=F5>q}SFBXl7K;b5||q{si~qt}^>k|2`-eLG$7#+mX?T^XZW-u-spIm=x6 zt#b~gzYbMbG(T;TZ#o8<;RBF9vH1o?o?61>aRIYDyzdF|WrbgzMm;t;b|&dIde=L~ zw~$;%ASoL@hLn7gYRr|I6BYZyZ$IjZ0{}-mE@6vv-o;A!1PwR<8mZlvcM%mA@q-1| zyh76Pv>k2V9f?43&3i9M;b+)x0LOp96fL&fe+C`-92D^c%O~0*D7ry}z++rW7$Wi+ z%T+wz)Ios~k($iW@#5`xnO1jd-bl|hV-&bHABv_ykEJTdgvHP(I5EOD zcG4iY1bMXNeLyDVcEHFmk0?#vV$cRfR_9A|5jS&@W;N>`9#loLyy(x)*LYk?o^9h96Gyt>Jje5^m`tLAnL2=5xV$*j)7|3JLs+tB2G*0*CF07a`Lz7afrr#7X3FZmaQ3Y$3 zEa|Vrb)I3MYF^p4b}q+n23pBq9LP}H=;yzsTt0!tA~kh730{_ z-yeh>KRD98i0f8zMu-savd#I{rXpcPG6a?Z2yAVx>h7%Tu;xe%?qwnOxYK;E)^=Z({YBU(;d5 zM|mt~M+ej49X&JCO$aPN0DDWsakxEa!%^aY1{fSiDLoC`@tc}PSMaQ&3)Hl_ zwR>*a;)3eb;;(sWS4`^EMG&BxvZwOL{+i>$6c?EU;f~crTD8q4`4UMGZHSt+ky?9M zxAS``ZSi}*sri0kCj%j)q0rR>5xDTKscHm3#TZ5}9d;@*`oRQHK9&TSh6dlIEc;YI zxtTfX>pI-Y|ExPl@9)VjiD;fbb6xJpe4kOpq!o)cb3QB1vtiIaQq>lTL`Ws?ST*3- zjy*Vin*EU$w~SqOBe4CFpWh<2fod+lnX(Bq9Z@5PE{M?^(JccTIIZ+$$uyFxzB!Rp z4~hr^!KKyzHC7SrAY728(X8xfufxlp6{DwAA{s4T^hjrf;#$|%vKf)A_u0I!-X4<@)M?K!#iNg6H)iQV zYpP1?OJ_E=_N^=1mIbYiOH3tL57foDVp} zI=(ICv^#ydJL}j3^S!dV8_+^@xi>?hQ)D&2J+ROYaJ_qq7}NTBs`Bc-3=~VDlQ!|* zJ!2q225RaU>0u%mKp<05(9A-LN@GW)m?7-$&*U_4ecRi?6WvQG?j^EZF?4o5zw;0y zhC>cZcgzpMj4GVETrgCTqr+d}7y-FcBYAGNT((zb;;z~Hig=KW-FKoj)moc6K7&?#(gJ>-tdnrZhmY)7ELyGWoL&ogB40`(q-_{`bEm z!1AgF%n_XgbHqx&vqz&WO>6mAIsqo5nGtuGYYqwQ-6J6_x-KmcWm9Hj6BEWMwUL?>&$v__u^-6VF<81N5aTLJVZtmee zp6!yIg8SyY)uFKsB-%Tbrt zUn0OwS2~W@%T~}_AW5RRAjWpBNn7ORr}(G`8*%7X%xSIVO>x8-Aw`g6`jVj@3&HpX zS+9{l_JR*uT0rBlhow}n}uI@K#+y{qGP^5A9U&hiW%cm?%2|*`Mbd6eCyO_&tj;Zp(huX2CHp^ufOYiIrA_x7Le6XuKG6@SJ+zO*|MaWnO9fK+}7IW_G#r+rOowh zh{yo5?$T`#fV8Qz(cvU?vsU)>^7As+k&eI9vdXScEqpJnr2301o2M4``=hvqmGg85 zR2A0mpQ$0+S#pS(^p$=G5&4myPOz(qz@LUq4Xj)>h3Fmp9~@aJce46YaHxvYm3WzC z%Sn0^_1P}Tyo$3We}kxT&3l>3$0%4#4eewd6qu63a(#s6fdY^O)yi`(qv5fWirDBA z3eEoABPXyO@C%jNi6#=`LU9#kjTPyhz4&N7&?5^tQh-8;)pH>OiO05ZzB}fY0LD!E zz6aDq%aZ(Xjnrzw`q*GLT#v}QTZs0}^{o>t^ zU!`1~0i0_`h)K>(qsq5x{uNXx1@&kaig6bFUIGz>fI}()jO?VimmMfs2pJ*BihUrB z+Ws4qW#(6u)tmOmRseIFCZj}R_&6Q(R;PdI8MQYHu}yk)vi9*ezq8Gr(B|_{m|;1!WXjcJ>MRq>dL9p^|#8AmA7t>a1Hv zxH*O&V_@eTr}x{L1vfBpCdG}yV!D_={>98bxfshT4Jsl6I@W{Ud=n}#8YH#e>uSPk zU0tVNJ3pzVO0KWw)Q3WzVgU|=C&%zNdOI@OB(4k|&2TmaFH0N&o?ks0q)XCU(QlO~MV z*WSSaYUPBkg??SyS)*DMYoY<$Qjd_W?>Hq7JF?%h)Jn|qaZN+y0<7)@Yk99m1#DW$ z*u@!I^em}yS66y5AC>Udi)eva+v*dfXxLKowZW11)%OtP{NI^+3R^q5THUE0bO;8xW}uiFUUL4 z)ZAWd@PnCq6wfCX0nE~5FwYbOB4R$qkN9pE4NwPgeKP5a{1EZWF;em|8>^Xexa)uy z-|_fPXb|$Z!FDeQ2#0OkB`_zgVG}3#E^09FFZR9!WC-Q`sO!0T&xRnebJ%i)ugo5Z zloF!kI5a@5wk?rmCk*`w!YythdmTCpI6g6%Sf_1C3o1=f*Yij!Fk?+_i5P`|5mPa^ zuBHwo`{Zu2!{N}pnbF<#1aM!)9OjjFU?$3qVL71Du4i#f;~&`(ZB#2vn3`rH%O(a+ z`ue-C&2)k=s!k!xUq_KYo*x^29v@*p41^e5e@jZj(TQDf$uB3>C!sJ(gxnO@;-(_2U7{Eme~0rB-flEGR=ZCu2R-iZ{`ASM%|27&ng zu2}#nLzHw2)o%E_KjAKj{J)E_0VEaanvUxtLIDFJ3v)oh$~7v97Q_!BbF@tK+t8B= zEUUc7Z|Q0ET5k_Cjjj<~;Xy>KYSOS{nM*j`B5eD!C53SLrVcGs1-TF-@tAZ*uRYcM z>S2H0O_>TYO4=rY%ho0d#*dky87Ixr1g0#&^fQ)*D;cb{O3Dh*kDHJMCNCwW>!SM+ z!vG}@LYX@-X;^z8+pL>a*Me$O(bLh~BOKBL<4g>Y@S}TqTtHGm+F!8OpUhw8vahsE zUN8@YrODg+)}YOPZN`@5c&Jiogzgw9-Ef;XV>tP*3oa@$^8d&mkmMS1RRf@_`5=w( zL)Xu(*<1G`+0W`w#}#Jqy(Xvb#?Ge}P*eU~!?(CW+Y>a;TX=t-^!Plzose}|`}Oit!ucM%2I`rM zqxN*m$d);RU>-)K`=w#)T~M^m7b%}bt(8Ujyjm+qP2?FVcX1H4%f;V(Bxx4cUxbX0 z!?-CC_myUNsJ*P~eI2X$eI3>O+z+La6;(DefQHZa(-$;a?W#_rb2MQ|2_?RGQ32e0 zlIJL?n^fk3I2C{ETLt=^0g()mzqNF+O8T%QS=jMljoY+<##nxzA|Juz_oMms{F)OJ z!W2Z={++Mw%GdE?Y09kIU#2ga8U@|%xyA-kyj~LMVDSwg9qg@Tnvk3x!xcMOWOC4d z&r_d}qJhRl#!pVqjKTIhy)QW-9Wyw4anfIMYzih&#?jRNhG;Fl9IaVB`*CtM{m=|- zh)jT)BmC@sd~6nGQZmAnq4>}o%phcf0i#VNZEPMULN3G9KS75weO}%fIj>U~6(C#M z!oSs6GL_}1QWU*9Y5h1bAi$DLqupQi9Tzw_Z4GSS#3Q=+P$~yka|I$vO!wt1qL$>% zb%_SBY&g=TyDWf~)T|wI+?IzXfdwKE};H0ThZZYQR6J*%~E=hP)UUHK28ATE(E&eyp0$U zGt^a>2si;(*J;gKltL924^oKc`W|aP67Klsv10kagzlpEPqNOkM4R*ukPF}E&dJY1 z3*XOnQK}C-M|#r$j4$F2Fl_Nx^Bdl1oHidX54U%>-@DMjoCOyVR^Qo^jtyXHX<#Z@ z>;RQ=aCFYRg6j2KqLU-B@x)a)oi2lpNt3yV+xc(R4H1=VXk9F25wWu54*wXZ@?`P$ z;qZs@X8xfN0($wOE&@G&7LVW6LyER1;Cjdw6G*J(K55;~)dHoA^aWbYNiIRBmdd(n zB9rPeb5QIOG7@xwl_lab1R6~X!6(s9%&{(pg{iNGWkMc|WB`Aj*G@A_Nn=^`TNlgT&G*iD+MCZtYrs)t3ynbaDX#&MNKhc)jM@jw@emI!~7*p?-K zO<*|IKRcq;LW7H8Fk`oB&>Ig$OjT=8Qd_lZFj6PFw;4)J(q}Vw49-_Wv);hzl!$Lv z*(A{|cz4k-c}$3r`JSWRl4jVE0I#t1%OX_ME6QS-I%^!A&^6VU6OrV%<`cAnC6XMF zO7@j=%+TAaL#1AsNS@sW^v@;%-}sh-smlMH!`A9n&cY=~m;M=Q&;|CT(4jOBGy~sf z?OV&ozDC=)!?IplqVBYel#a=kEbypDl<}W8Qw4M;iAHDr$+ji&HCW)%;CtYJPYn7qZDz7uWH&!&+_??8 z4L+p&!u$M-Q#9*hrSv8!bHRq-vRX*?5OIKq0`gzf&aNl<-Re8+jY zV$;TBoa0N_pHxifBPg7p^pYE;M@%pnFYlG5{|qo97N2d5_Yq$HGdhg+`*;A&@4_Im z=c{&T$0KduuYq3L{yKhI{$Lxmhdh({>1>f!XW$gpr*Q{C+ zACO!etw*7Ca1sL+Yv68${^#{s@8^pHKlp(HeAuDbFH&;Np$g zfcf>kdwt;IC)UY<_L~AsoOak#w2~Gbo`|-K{eaW^YBRCxwpFj%eISa+Bw~UW8FR`% zYdAQL%BJ=)r+rBCsBG$iM+&|n*tv^3)&RqXHNbBf9+eMR8Tlq+tBfI}m7_YboCup-}%g!Ufy%2uoo>1lbKnV zyIQM5FTHmgt8W2-C@?u4a?m(m7oy&JG>WgcD8dKRtu+9<8|8Z&$!^{HzqUH~@CLjt zbRFIGof6?tKmDaB%?r3M4jYIwDn zoEXzD*Vn4+Eh>@gtv?_kwAw=8&3G(?#r$=(hp#Je-!g$2nY3naACv9tV8HW)TJ2vj>a=h#v|i59DGx~|xgI7hnm42Gpu$G4c9SVjk6~%qfK=m`gfZcZNawl!-u)`D8yRsXo&4E+sTt-~rXAr$V4`)7L2>R-E`?`mS@YKc0 zDG01I5-_Z@yq%(KR-bGkf~X*qHxz|KZHqIUUX}Fh8dBlUT{1(e5>cjEO_5WMO=G~Y zQW_mj@h0n2#SV>GUk-32eKhlq-dp+WrWagwdq!*HXR8>I~2aEOu$D%;Nve>AyS7Q_?kTQ-325f3qg}ch)urPR=Hd|6kt! z@6*3CZ;Y3T?C1acVf2585x&^0Lq&!!Y=hK9egKDBSc7xpOM_|rbOCDA*1JEvBHi=Y zjaL6WHMGl{q6dYRR0t^4I@lX5-a2ji+44Iu8ZbD)6zxgE_`KAu`z%;T(A*s&QRjm! zGbAT8hg*~1hyF>U7(GO3U>7mOW5o1gBR0@l(M!X}oTW`WXD}ZPGk`sJmofA;^fGfg zbf-#=#-o>oLoipO&!=F8GBHTwQJk}%xsbF3{I;{+F|gLd%yh%Z9RCG~%d{Q41yP*d9qK2)+syP{-VxVu9aa%^ZjD0LVisE9?I<8?W!} zmyf5H>F!v&z4@!=37dEVXYZQPlVjl=;+!LPoEf_NOa&!*kL&sU%Spj07-IPY{vGH@ zZ|VrH2Z#{W$i^xA>MQjC{P!vI>HCdQJ2u?NJX-KdB8f?fG8-;D{FlE&z^7;KLEsJ< zKJ!ckjuY_b-rzm0Oq+cXec{e?J2ZSgw z6aP_Jk1-KvRoOaanWRwNzRi+jgM|HB&@LwUT|og=Kwzb~S&L|vaoFOhqv zJqBasBa`Z)KwloHI!Ya=IP09RTy_YeO>uGLSWI)W$a7kgff!Yw<{*O&hDfCDhy@Eo z48P-o`Y>~Yg6FR>iD65^Sm5i(NV$W*XYj%1#hsnvT2Ux!o!(8LW)oB?GSK`n7v> z#fqaXm%qs;tZ9nuPCyf;?=>K!k;eZ*SDeJXDZ(WjsT6eUxOEiR-ACamNKX zth+`p$z~a?-s#QH=lM`JH28;C*H$Sy+>fVgEA%|O-qXvC;zu|vSN20B^y6AEI{t8L zumh%=i+8bMP%te1K>Cu)axa|PDd{Y*iK?|W?xG^OsV&Kce6e4Yjl8Mps)m^hw)TET zK!>t{O7zbvf0-4*dT@IKv%HoFfdDm7bPKguffu(CMi0AFTzuh>A*N)@^t3;T5Lzs1 zm6VfbBTfqdR^j)g_PkjFXxBN;7j5*+z1PInt9?vkcjW0QjPF3f?5#SH)T2hgX{EK4 zrm5VTi|d#3H4`!S2?X(Qvl$S*!>#X~ z_@{4XIMIunm)kEs@3+>M+m`R`37Q6Dd*iRiO+e*@V>tCWrA@*Jq~-ep9O99SHed!3 z?3{NjxjF-I&e<;85)DkR4EuEKp9xc4E)hpE^;n#F9$D z%^a-PyGlaEWGko(Yv21zEg!+94lNfq!jDr_;%#%2s_Q4zY!H7dT1Ij#z645=4%;Y!*Z&JQMr zm7N434Wt|-Z3|SgDjCwfxP^rY+O>e+Ep^zgO4=>pR7`=Y)NB>>eCy+2 z_YGdDlKNh$GV{7P`!^X93#U@)*tn8YqSHe=HFB-(phA*j!1k<19`ia>E$E{N{DE=% zn@jyLWeqbp%EfS!ggUudt!-^N8r}Cl>OvH4A=Avin$YX-jw{rEx4r+=KL1udS;|tj z8w@C$=%=`i2UH1Vv8323L5rfAz;7rD31m{DzRlr^MUr!_n?jEepzWuK?Pp{yXD4XI z6r9O>ERom3j@y%+dxfE4FQ5&o1k_aSfwfme(C%cWN%TmK$`3&p8exU0^r3cRKvYtN z9?5yy<&L`?Dk(w&R2_NgD9LHm+{hus$4(gm4FwqsciNYnp!qngO~7qxw353SZgj>1 z$|lfl=9FYaT4=q=WDZ_2AfidG8b^(lFdKPP5@3*2q{;+p{-VRhtl1>uFAkzmt&;LK zp8)I=AYb42Rl3?r>ZO|zO$eizAfT?R4@U4t^l$|X=CxC2Hi3d2v0J)35ASrt z0)Ntu0mixVaTJ@%Ih)=YO)hWFk*=2xELm`Xjg~bIu5h!AHX zI=aT&`Tv!Tc^Dh(!uTJ)IKwU~=$Xe2PjBA30quLf zMVs_BTAYY$AJ7!(ctvRP8-6anzVoQ-MC20*b5Ug{wQ37iyl-wv3QcP(l{d#0e~y>0 zF}`YpiM#c+eowK*6{W4IX{gAHZ^xLT;df)lok6ndX8>gcS}^* zxU7^EbspGK`xVKYyLFE!?d*SFA5`7Q_n1zE8knto(s1Ztrqu0fpX7U;71?EUBn7*@ z+dGRE<}ZYn_GGv}?eLF)PbL6!NyTMNN2PGu2rQk#|D%YrIN4zz{~JmD-zs^=|6k9> zO+^4P!ua0=-pD()q${WkUryTeT@=8}b2*e;K8BTyzCULMLC0J!DTxbq(~s5tKsK~1 z7~~cNsIuo#w6nZ&V6|rPv3tpD+u&Sg5n;9>3++^?jnHS3(Q$&eoB5P;uc+P<(Kx?>%h_E z2~Y#045%#VN-yn^5HAu@2ZIcrFvne6e4M|6tdIc+3!?=_0zl>rNMI&gy*2ZlL` zdgYM}bC%#{T>T*WW}dZDXxglPCch>`peNZt9etiQUVPNa9G&|yxOhaIN+QH}FePLVt1wxRmj>3Y)O-SyZ&O@VKFJI(>e^0APQz7(FoG@J-i6 zvYVHWo6|+M2V%-q_ly(=pPE){slXN!)4T1CfU1tpR)cgBcaM;0%ayLbKTO9$gN?G9 z)(h!YWN7yzesLxSx=w{bDdSj#4Zj{;YTM!w_~h7*yXcA+(N{BRpWfTA2?LCUw0cAM zxT?_A^f5}#J{U4<89iBsETC*zhQy^Q@4nHCo>aGpEfO7S>Q3R5{?`>i4vU;p|3zyML z(q*}g4ZGTjj)hZHob$s;CP_#22IlJ!r&-*NRmxFK`CvJ_vpd864}A2XQ}>Gcjo@V) zO*AX@^1sGWXZ-J__>n;*BnQb62;y?V--&Yh-|?VrLYgE+@V?x&1ef!m2~vzf$?7qX z4SVe{JK{l;?b6>QjAQ0@&u5=D=-z z4j6tJYhQ;aOYy8Tx(Ok6DYBM^037o6X{rtzW_g7WswBouVo)Gy&B6bVrP{pF3Bnhjgk@Y5axlRnG!FH z#}`W;)TWy?bE)>gnf=iDBZMy!1fw!ee_lMmp}@bMc71OUJV>VK{kO#iBwQL0;x>!K*# zH_|%-GW2MQm3+Occn2_m25Eqo1gxQdVrbABn~IhyjSW4ME$sHePesf!z(BO$cg8*!|C_mr(?Xk;z(fBC`RDD-27mn0ab`a1>)r{aVAC&Q3!NJ3uy-4ARu7~ zG=}XPYCBsejGFheShWfwi>rpv%@ z|8RBK4#^>xS>MG1WhUq{v9M}tJTUEAD_dDg@$3g!-@QMXZd5Dp3}rdKBqvs%tccJB zl?2rPjs|c7W7q+06^LAwL2N{pQF?l>tNs(6vW-AdJ1dqYO85y-kc>@!EtcUu>o@&% z0{VmK+Ds{bbX>k}ZOIwIPmuqXkdf5-0D^=2cq04)z|}V%1nHwWY16-?TZ&L}lOLBV z(Rl7AT2f~=GKSNf*$?prHsT&1f(A97_$e*mdgacbvz=0zpTmY#TEMSBPpM*HwA;|tmdUq;w9hcA5JB4ia6kp((9c4z4lr@f1Vu+msR9^SvBlMjW0<_wl; z(ayyol0g#8A-(ON@0pWWy`RrWEyYwnKJS7^qFWF*o<=C$gD@Z8E}7Xddj~6SH|^_! zgJL)MwX*G89NeBv06-8K{DnY7+#c-XB#ddC@^9#;4zH%mN=4a zi3sV_+F|`dzAFsRIq5s@W&&3@ovCVw?XD0Iz71i)Y_lX!tW?=egC0lLsqnjk z66O4QX)FQA5J)ziPupB99r(*y>#r$Z$7|0)-J?ut7**`3J1osKr+Ee5#20hx z{c)~$Dyu;M@Ku+Q8q$z0s58g!(4Bnfl7nZPr6FC;?&p!b<@}jKSYYi%@Gzth#`-~Y z$eIr(j2${ep(YmWSsa6-s~7)mB!Bh+9Q5aP^(?=?9Jm*{o?PIgJzbQs z2C$Da<605Ziy zvc%A`od!6v)Ya|o`ug$OYg%EId_$y^IDSG?Jd zZf&Rdqhs@1r-z-hhoUTnrf-j2nE?cW$u2xFr9L|c@0Na54l)~1{$5sFSZ;;@nVJ+% zX38a0Su}49IcHI_qw0K;OLB7GMTW)EH~RcrAu1!D%*2sIPKM2SE=grfURsDvy*$wc zB^?GF9ToAFtRfV2-)O~P4AHzkPa>f_vYuqTqVnQ=u|hqJMFE|4fQ293MInAwrQ;bB z>fGEuJTTl0W^YM}p=3N?%Qbr&IJDU7V@b4Q-C}3M;*i6(2|wibC8VC#l56=^<+9@{ zF-SKzQti~`2Qhf2>G<*QL*#4;7B@zg05xHP&?b=RpVQz@&+^1V^76(Or>kH6i%0B@ z*hk&C5VQzqEWe{X!UHSs@qv&BHma|!ZCZ@{u^A~Bdfm0+VXuXzc()^-vQTk&N;`xuZ#cP9AEJtxTBNgN!a7K*Upi^v%MDlcO`GBe|>BJ0$(idX4W@ zoV%5(cG};%!=F-A=X|h)z{OpUXPUSirge*|-67v-W!F!!;rBq&2p7ii>QS;{cWZ90 zn8K+`kcG9*MW$Cj>#*M7{-nu{3hlYbBH{>wokQMV0}M8J27vYByZthP7;U%_PqKp5 zA&0pd80B`%bcow%5enZ#aDzM?q`Y2qbR*P;;uhP5%{pN2ttGS>^|)>vbW0BG^%H+? zm{vSQ1JX(`NsvsF04^wUg!W?vD-{a72*BkK{sv(o&xGP?9mRNqzpa$~q)V*;Ch?va{+M zW0>302VH?JbP%K4%xg_KH)K>?7)2rQL}#O>mVI;v~!4C3x{Ip_5%^f}K==S$JR`RfC;osWA_x_k<1+ zm!e4uHr?}8JQ#a$OH6X`?NG#fB*uphGJd&OKiG!x*Q*m}vogLSk**JjVrJ zemE%~F`0o?Hn|9LzY8fk&ZaqFd}_done&5umhOXYQ^V)Oa+UaIAOvKQ`!i4I>AU^D zkCzr!^uDk5JJisBydAzD;b~Se6)LOhYCMjaKHJB$lodJO-Vz^bd`Iq0LtQG-l*9rW zSi-+qE)tGDHGQ*nf??COh-7Q@>qY#5hh)1v<=3bBm{O2*B{_1XXVD3%KjsdHho&r` zcXf3`LCY*0xqq%&?0)?qPXx9kZ$!z{$ypbRhOqq!*F+hL#z6fXD-%@MAN&Edxtlks zC?0=YJ8)|r>Zr1`wW)%kWVwza7@gz`SFqFuKckY8mrLA*r~i3B*3%2J(e?h=ceGK; zxNDChB<=Pn7aJER>E8J#ooqT1 zeW&yL>yK2kq|5r%y=q$ofrVEbdeQjW(Fn0PwM^W}Os=l?TP!^FD8-YH)XR9}T|~#q zA{X}=LV&SDa?3&=sOh}3`XWvC6@UXOe_VabKFFMV&{C>|Ulz5E)WPhIpu_P2LEvvU+V~40^Yn>@l|mK!L5-8HOpG+i-QHsR6AymK~v= ze?I^g`~ueM?Ok{d3sox!&<0)}`-h-SBh0)a?pJ38s+NCt)5G3OjvP0S6Am>`9k^gk#JM#XBB zqn~Fz9g={!#;tq?m`G96s2WPjB7{29@>14|MIB(*66ckvFPe?4sf{8lDpiVG<2(KV zoHfI~Lp){BohGPt~?0Ii6&I{r! z+=0iE7N$7VPzePTB{1v|dBxBJ-n&5Hrk3~85W8Y7o3rVcCG3p)y1^rWd~O4JB%8q! z_dS3eW%2}(xAg{-y$va+wVxg&sHwn{u7+P14e9P zUmHE>4c>WgmT>Vk%Yr=Yc3dMcm5||YAhKER27S&{@$=!Uqxfzu4Ld-9Qy^ejkCdd>M zz4l0R+NU^vsM=u^W9H!x9Nx5pyx>ARO9TXSJmV3Yy2!Aqs4$YKD3hT>tO+Xp)woBqHJT(z z+{__3Y8VOij=s1QdMg1IOGhraqiy2da8c1TO^OlYjGjF-F?>be+16TJhlwXi-VNFM z$M5=4Nq+#_r0Aq9`8{l5IUc0K59bZBmaiQv%R#Ze#|B(LIkud2wE?Lj1@VN7UsM6R zy+${*2@m^j-dKi$b8$54t4}N9HML7bI^TNvn!{7KQ@h{-4#_dCc|EqEbe^?J+Nx$H zXr#cZC5RunK*)M@Tj2s4Rj^+m(l<|VkEweC5^&GU^~;)s zgZGi7#_K+mQD7rbC>8U}5kV+tThJ)54yz#63;f6&zeRi2*0$2uvNh-|m}IPvNtYd6 zZBO2(IGvuK<#KeQn{$TGoYSJ*xCiUGweH;GvfxM1JF+j<60d3-o)WqFKKrf?zD2y* zF=zJgtlL9UhZnY{kF41|tjx@~TBB;-l`bqf#1k#VW4HNe#>ITzB5a^dU9q-H*9Zb z$i4@;w=hc_SY-W*=618q)qWe$N87`b#26kq_dEwHEb>of^ z*_w3?$9`*;D-3saO;R<}pq`1ao*^b787zsB`@MO7|lZecl!N6K-<2b{pbB6GWJ_b z`b{@OTMh)-9gNJL$q^O#+&W7=vE>7Q9S9d4Kh`JUOj8VcErMmZT{tk ztK4Dqw3_)T1tyBNo#sml=W?}}3$b?A2esGw78~kEi&Hclyw?C8SCf|dJ1L36{Db%E zlMlq`aN?Ti8Rm_GSt#Cpa5!4ciL2VO`j&`INo@Phm)qsLpam`RR0p1hEcU#Q;X8r_ z9@W@y^_SPE?($2djV^1h0Fg3syM)elR2b()KfKbHgFi3(NlxM>ZKY?o`$RvmmVhvC z58Hib0|QdZ7msVwLYAT+6U1aS`VtKb<})Uh z60x4zXAG(sP<6~QRB}nq!JfFfnVwg( zwT1WQu*=bDoo~My4t@so8%M$hKR!8!OPRwaZG}HmSp2WSMi3yCOiY2)W4LcmF;TL-fYo zAx(F6S$pj?yXwCl8dKqs%5`gwKxNeB2{Dk)87_tNtIUjqRfQ?X=eKZ=IRQ!kg&@Tb zFE-$?7Ic|{swHB5*L}f}?j(OJ(3VjFN~4x2r-TQ>ay3lc>{6K=x06u=sXNaRn;z7> zaaSCjib8!yblxEg^211An`d-mcwhX|J4odCHQQw1X9G^>T9&9G5m^CcxpUWp{$~|keR2nB^27vvOpO(oN{Um91Mc!nkh_(5)Mya zUlR5hd~d-Y2tZeWk64B?<%KQSm%=<}h(s!cnFhz4FUXspH=oY~5mhKdX%Zs|%_Yz^ z2T=h#NSc?hkEqtEI0Tx~wkkfPq7k>5A;e!Mv2K~+-Ce5?RJ+95U0y?`5Sc-NaYkv* zZEx900mR|x4gOw83yEvEVT+-F)JkAFpv6Si*B5qc%+5kn94AFQt$1!IQER46rv+rp zyj}sJX0h)*5s&D*C_J@9Y`l>$ZB-WSgqfbc3>!~*8R>0E605UTGnwEtQtInWMAQkKVt9q}R8J><>&s_LpA)-8wP(iWJX#}I85SXn`gz$>VRkB!)F7r$9}bPHbH zXDMnPe7ri58gRUti&m4!jwbj_Crc(E(?0`A<*h34%o(xCWifB-=5vZ7IMj% zPvpiqv@HSGv@9p<6mVBc(8aklv zxq`Eg3ltAa-|4tRS-#thE2O*ypd+*Udav#Tu*H@ps9PhzJnafG5%#7cm6r-;32Tz+ z36JT@PH^!T!ml17MhC1pfNnGB75q&c5Egq2i0KC*GM$VUlByCYZ{p{w_})W7=#_53 zkL9)bMV&;kX_QV6v*^=Q5o+s8WXRo&gK+bPCafNeOPg&?WL=eX)zSrMD;3WX`M&A{ zPdFl6c``gm3*<>1U_+boDo`zKL@S-Kv^350NdS$#X0_x$qk-5z8$ zl^W_R6{4U*-#+#_s@sT5=oLkfAF>K!0A7(6{D~t(6i#)qL-eTRK2Nw=O^@|VGBL!9 z+SAN??^WfB2Es@js@hvas?VerpM7w1Jnuj7zVpk>bv<)`t~G1cTF<)IbAP|MAQjCioU$Z| zrE-aG)Im9-Xzj5NeJ-YqvQT@wH_~-XXK`UqHe;Gs?-Nx3Vvd=Ct(b*~EP^ISSB5EG z6Vw}kP_Og{+8rsyvfnX26pA{wd-!sJUt*DrR9F$v5gUActb;%+qDhHc?SvZ!ZgF%k zNnbU_F(WP5O7eAd_~h2E(p65(hL-)YpMWGTRCY_dD)J;F z(6G6L*_mxjUk63*G3aV(SV;U6A*raRBSyNZ~1B`iS9;i_4|`Q4l184v1F%|*+jmDJ4RB+8=dxGGQCKYn+Swq3`72Ruv!g{VU zZ66~t3o2`kZM)Z;4NgT?CCPhJ7|ZB7R`TxlVX8ZaPiluybF@x4J>FU&s}Zllh7j?+ zg)C!jkk!^J(8%wtLd6ZKOgn+WGJxHiWwe^BzoPd`>SN>WjDXwOhv!T*BpK2Hm49M!Dc=`xzjWKttIx`;dulY)?e2TgIz;+2|RDC=!UE_*_0d&Dr zx${{u#D<0Y9c`&VeXIADf_C`Mm!6VoSIyTGTkHWVSd^a^uv4W=L_)84KebgrJk>0p zeN&q=NoCi&#++~LD6C|Ry}vh!?9kX0Jqzq||C)SojAd>Z9PtjV1UyggSiArT7b}1M z^n)~}!C(|9)|JvHfc**6i%5?O!`V)sH>}fY;mMP@l|4G_b)?G6l^)VDr2^IEB`D2N zbq&BU>Grr~di!_f?;c#j3TZ;>*Jp+@VCuFHQID<>P%v{+ax=ORdOKOmaKZZTbu*N+ zOA9xk$*);Fk;f;1%j>=qLwdrt^*lB#x}U7s_T7Jb27j#^^F@b0oNtw+4xeNgOWP27t1ESC$O1sad7 zeT2ehLF-(mEh}q#WG_j%dsvoZF^B-svj$~dt7`L7fQw)fRbXKQHGv}6H?oon2vQ*! z_+VvZoI0r|1Qem@)+<~LS+SQ?QRFZE!*4dU4J4g4S63S;VJ?Y|_ zTS;r*!U|ZwaDJ)7nxAP#_qbtZE!d~97kh2{I}s&`?jlBJsa;;JUS6xb8|ag3MNVsP zyffh)_kmzLE8Bpc!a6$^_Gsb6K4zgNh$?U}b3g3JS|wfC2!&f{j!nxNZUa*EpijO40FYl$Kx^q){PGvgC#Qe^}nP%PW}Zdx<^6CO$e>F;g*9O}@{4bNej4z6 zZx{27qBHVUmh5THR+JVgg^YMG>q`jz$Jq zb8v>dK6{B$>l`B-I$*(AtY)5JK+m*4u#4V6AVk?M7i+2Pf#)dWB|k4t;VMDDqvA@( zn`?!9)M%X&iO8KsQ5k_3L^6%$3%a&yz06{X@d2T-Hgt9)54h$s=oDlVb5D7*=^WzX zYnGmvno<>{;vUYiyDueOYxcZU?5w>SwN`&M5AwPgzge9| z5rnKtX!n)WJEGin!)0@`Ju#El>7nqmTm@*d1Tme1b=8N7Xv^y|u?Fe+7133+exIYa zi*>1&l=9r>By|@>YB!Y?Av}!(ttAm?@4~7@uKF{o7F1GJ-hE*9bDdYUY9f0JP0VA3 zJ#$Js|165-aHiX1)d^bDR09%xlVV2h=)ggy5|bmLXNeVaB25X@jpZ=v9V{faIoA1wW-p`;rI4B zqp8tKBH|IaO5mzfrf#L@H(-V*HBrhaCgV`&MN`Y*Dn9xo6wZeSyHA>@AR$*jrohlh zX+f)qK{TSSp&%_{V<*ztFg3nhJ=B}LxC#HE6HwZ^ za*=K~JbAbycNX?T=DH}*aXhg55SH2!6H?W@Jcdo`ai$t8-{LbRv^@zgtb&LgU6X{p zv~Pd0Lng{w+X=LpPHtuYq52$G_YpEGWh|;{IYGU?dL&-&l{9{U?M_B7Cx97%w~rj7 zCNABc$L4%5-Jc}mC%16&cyp$BIP~MLkpOdSu`B(hIOPi%DFp>P8(ZK=Z307`w+;Y6 z)zZ*VLK~5#R_ASLX-V0w*z!IZJi7|4x!gQT;wHQHXOTOs%NKQo$?s9_?lC6O*dN8G zFq$%{Wb&1U38sITw61d>f+AwaBk^}~M0K`HKN3%pY>G)h(AMEuiDG!+VL1d@+b-cT zUj>4~#WR}dA6H-%puxoY4)Z3bn|u{moKVrcGTSX(-e7 zo0&kTF-KuT9VpYh zQ8ML|P0a=SdV6|$K8{8;@{^vOnbFnNC6;)}=F&C4xaip{m2L709ofCSp7jH-l=~t@ zH23M|rX}+?Eu^$|#jCT01+p7ocRgd{u;aZwd!E_JNo^u50tJ(8zo>h0S#=5Md1I=` zH>1M)m7R*;Pu*0@R8_yIRCjfC(FRAZbfumSBQUvQ+W<U`btj^$$msuj`< zqc1jd&Q8(`^sfpIN5bQUk;PR6vBgzIqrpBfZy0_lqS#WzL>)|bQS?BNr7EmmHGa;M z;>(oio_k|sqsupAckCC!GGBNPyvc_f(pid@asmdID&O^@jiXJX30n}+FI7!*n%doK zqJFMr>nW+oUmVh8`dOLG0*(9;hu5kyI{4Dr_U0w3aOtkIzNEvou?bYFC`JpbgEGrh z7UG28QQiKLmSBK7Y~uIwNm14UENgg~d<48u4t}WqFFQ6b8%J{|FSkExTI@9qoj@G; z0ogS_+d=hVi1gx=NM)?sV+!Sj$>4q3f_^#`(+BqELdvj1F9;yPgZ-V~LD*sA`TY7$ z;d`(ZGr=QanHkS`86PITs6!3+k*}(_Rqw0L4-@Y9JXA@1#aI#B@JM4yaiYQr{I`Vrj_hXVqe!xQ6}I#ss1LF|Rj5exhgtB410+%-(fX@uum;JqM78^v{;+mmyR53%Z2jL4*|JxfM3 z+wD@q4}9tv2C5FMIoFv-&y75w2$S&(&_Or77eJ8p#JhXgKfufH8aCBBd?J^xFiYMn z5R|VRr`2o6)ScV^L48=jd4+F{yGjU?W5mYynphi3^t)X~-k{;PZTS8J3a|CXK|n+N z_b$W4+4+xA2{+(Ggq!8Uzwv+jm7&?;I4+LULUV*Ym9-pakE9)%SIZ(F>YGEYu`o~M zmjV9Z1!z*5a1KVkPp$Pnqb&H%0QM^!f}LTU`!~TK7iKuMD8Fw*nn%ArQ#Gq|ODbH% ziXu?_QLwa+i)~(DO2r^5fOY6~fHN$}W|qZ_E(#2x6Y4m#vo}vdUAw1?O;>Q%KOrEJ zGa;+l*RW5`8n2Ml-_SMoyhITXx8r?8mN_L^%jB+uCci7C**l?6gtW=4FE?)hJUZ$t z!!ccrvR#OnRO3uuI2?2BP5Q;us}BL#P#NC0VvB+1_`ove zmCX@)!WR;4q~hOuI}~@neml9ku)jQ8uszzQ$Z7~UdlcGhtKi?%63A$P0X5-T?Saej z#`KeAT7rt_cDP;(MsAc7Jv;6OZS0PNK+q?FM^r)3D_FNe;8oz+#_9lY@>1`nN~RWi z(S0eJ>W_p<1RhnhNdF>GXL~B%*9%n(v#oEa`0~~I*=$GBlXpj3)BfWx{k#e3W#aw3 zX=Kv&Ke6pQ4{Y39t^Is>ugi}N(B?9-bO8O%;^e(xR&!|*k_{i<|G5bt1UM=czz6>W z`1HX2b$XaNxmx`H{J32cq7phBCpi8vQw|90I|pal>$T4*V^{bhX@$#BI`(8)F3`tV z3@5Mw*bICK9vb*OUgk~nNOuPyl|CCD6f?HG89d&5?@*{(gtZiN7%ecC-(;MDLqF;7s(Qk(B3eMS0<`g29(@)TL6ni=uh zb!=7N?)}~;Bm4!$uP_8(b+T!-!SnUAlP}p$Vj62{3$OsprdCXPjYD;52x{KLDVpo< z*ZxVA9{JQpD7!e%wIf#b*i_s;>S9u5vzhz+prXQ-sS!W6OT&CF`>?O0^5d~%VBp7A z^PelxWi^Na9!PcWhSN~o&oZJ!cIpFpNvkNz{CINW$uVkF6NWPninf@jH6L&6uo~)} z`6Onysd%cC)*K!o0)l>aDx+7oq{=t zdk&SLWb%jdOh}Rl`N84+mV-UQd!{%Me7USPksv+j0>I;O^ z&qGWF{>ax0A?@wpbpjI*ar3&S8v<4-h7Q34D}GeJryU%PZIOh*^}39~g}HQTQ5`y^ zd^Jz?964FdRbzo!69yxa+Zy&yjiw7eGqDRr0IP7`WNCY9xY*Va2{?~odhJvu5U^t( ztaB~Z&pF}+L>@+`Gi!7&(|9o0>_|>a>v3>8SjR%z(fuDiq?9(}0ix#bJtE#WAwdiw z(2_G|C8~Dk_3f)JzGNKU%r>%OwWVI!BG(;kHAg>7#`ULmpbk245 z2u=(%m0CK2Wrd841|LXIMSs6G{;nqzI0DQ1*2LH#uplySb&Sg*F`&85`%O7dIxM!` z%%i$}kp%cCqB3!+phNK-@18>dQ`UAnY2L`&+}$?vXam0Y5Zy3M;ee!dc=7jNi!dS* zE5d(s^}qdN{`&MAkAF3#e**q#G5#x{20r|MF&w`ec-KYwHWUM1H1nUH%6H@Mx~AO5 z>p%HB{=ayr+(q3r8M#Gy!W}36YRX@-+uvD^+@;+$@3^Je!`)r}qW$ky9(Rd%{V#5b ze&lzFzqn!C#oW~s-(pI!<7vDwP6>;7o#2NpIxb3MwtC{{ZXSqweD}}tJ$us>; z`@5(9djFGk7jsu7b&GLl{XOPS&D34YU5&&oriJtO816ro^1GP3#a*`;C6T`|x4rz^ zA9VMC@)j`wKeGIHBJq#o%Dc_Dn-$+OfLebyNs-7+~TL=`F(l0FKZ` AJpcdz literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/内部图5.vsdx b/pic/UML/CHS/内部图5.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..0e078f9489e10b7a69eda284dceb567e090e32c4 GIT binary patch literal 37002 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≥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

}D*MdzG7I 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 I{_*es0YP=np8x;= literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/外部图1.vsdx b/pic/UML/CHS/外部图1.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..d72bf3abd5881db92ee963ce125ee37aae4f6337 GIT binary patch literal 25813 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


Cht9|D(=bnG;1I>GR$e`Yx-> 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 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/外部图3.vsdx b/pic/UML/CHS/外部图3.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..415428fd555f4e0c9c3621015284114173815199 GIT binary patch literal 24144 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 JnCO1r`adB!DBl18 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/外部图4.vsdx b/pic/UML/CHS/外部图4.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..7b520109d4c584ea6d814d73e90074ae02b109ed GIT binary patch literal 24461 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 My$tZm;ID8018TsDqyPW_ literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/外部图5.vsdx b/pic/UML/CHS/外部图5.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..57d19ebe03ff5b03ef2c87a7b69499971c5f47d9 GIT binary patch literal 23847 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%0Aq_f6dqU-GXz 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 JFa7!He*lIhmv8_8 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/外部图6.vsdx b/pic/UML/CHS/外部图6.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..f9b37008aa44872fa7f8733545d17da5db493dc5 GIT binary patch literal 22257 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 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/架构图.vsdx b/pic/UML/CHS/架构图.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..ed067515068cbd378c86ee038f030056c88a9f82 GIT binary patch literal 34692 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 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/模块图.vsdx b/pic/UML/CHS/模块图.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..c6ae0262cf1790e034519e223f8c692f3129919c GIT binary patch literal 38563 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 LtFm$TzrXtrLubxj literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/类图Modbus.vsdx b/pic/UML/CHS/类图Modbus.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..8274648e84592422812be699dee39602a6eb0aa1 GIT binary patch literal 70225 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 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/类图OPC.vsdx b/pic/UML/CHS/类图OPC.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..350a6014f5498f1aeac47baf8b175de82220c914 GIT binary patch literal 67802 zcmeEtW0z<_mSx(uZQI66+r~@Vwr$(CZQHi(eCf=2RXtOyXQuiWbl(rL?p+aI&R((i ziP+~{c`0BJ6aX*)2mk;8LI9L~`R{T-000*#003kF2p}zCTN@{18z((wcROQ89XdB_ zD}n+LAc{Nypug+?=lO4pKv&AR>>vX|$gOyn@Da7-R$X9*gFdGa{4rpa+k)m$q*ZHD ztLavVP-TPqSUZX2m2c0k3mNlZX0cTxs5*I5g}4TcI9SDscA2?o4mtcA>3EiDM58Ko z*%&s512Y#7hU^YZ8_e>AiqT1Td&$x=bKDf_hTlN^FRgJNz70y&Djx%-ywSjZ&g$le zJg*yJ7$&S8!NHU2*_+f?k82Pk;fBrUF29PfIKkejL5S_j`ne8VMCKAy*2gxk4tcLp zjh%KX`Sy%MlYutkrf*onD67tQs52+Iwro|qv5~2FF|v7X9SCi-JEPdq; zuVTtJ<61Y2U?U-Kj*lF_&f9wibJtiv=LGd%n6qJ`IHh7)MPgYcVp+vvS*2pyMPk|| zV%o)GNr8A6yhpCV@}Mj}p}&y+70Zg<{^)f`2^iXkxT` zf34q;@DGnj^0sVnSgFu_8c4Np=g87G z0FE_Ybv$kUWcR@}fzPVx7@6n(yE%V;fC1$HFNT+@4>XhhWwGeoawMAK7^2EmY_0Xs`tE+;r$JH&WX z$7%`I^m&K;)Uhd85C{}RsKXB$A4!8C+r)r12(A2RVmwtjCNzdd!I2TRsfz}|Incc| z?*lR^w-ZK&c~oiY4udu@vL;`ei@1f0G^<7T=&(AHbO%3t=uAyH_usOLIOC4p7zF@e%pU*% z>F){`b4PPqdL!H4&engk=ReZsmCm*!al5^*oXR(N%B{akyDU-pEw#B0lBh-UVyfu% z=&`j(z=2yR^ORkg&UPZT`vIc=juIoHhST%M21 z-VI+&pd$`Ux)P!pEP1LNd=_#Iwht?BZ@#QBa|XT4kU^Go@^2GODt6!mXM6P+;E@!ah_?-be-QcyqYw5qFrZHj z_@jtU_s5BF%+JVJ+>vO5Y;M+fzB`^@z6sz=K%G4;T^&t*w>`)ZyIs@6?5R#>+1OD1 zcoO0UU+It@ozD)0ar*pni}uUV!CT`ocr9;hndM$;7f6tWmsj5!SH3&G^77;Y((BGH z{7Z7dA7Ma(mGg4VhUPOn-9!N2fc2@-vkW2rbV?)%7+?H!b4cN1mDa*%WKWwMz8{_C zy^YJ_`)1B5L6XMN!k$m!!!_s#aCyHT6L4cKSX(!C z6WCXvX+W+PMz@4qS>yldq$w&S6#KHNT^$KodB*r7_(>l?DZSJ4Z3_J3V?T!zwAc@X zwjIe4q(WO0_$u2sux(~_D^#kLy}do+0?ctG8-PLvE}nfY>*)xcs{?A!6uLZb-h{Zc z=J#{jJN=6v>IR^DU7_mC#UHd?5eylyd7dAubkyPbI7){E7Sf7M_H=ugN2-Jqa0KYb zdCu#HzSsRH^XL8D*T+CuK&s#3GJ?WF8;2$N?63kf|Cje2(m4eS8i1M|DL}G6_#MuQ zJHG_HY2%sT%5K5)@5NdXH}-K9>*{42>z3B(Sy@b4)9BhWsxkfWey3zl`)nG+rE!~j zT^=s!#iMJ2Pet(xq(5CRVh40lq}zH6#rnA&{ZpiA7q2Hqg4%2B<_MMJbzqg5(xz*P znW5>1D+LE6{Q}VPL=EPac<~g=;giW(+Ph=0WQDCwij|@y3yiH{LAY|RP&qtK3oYn? zT<8X$VKDN*#BUBfIgwY*n=eQQkyJz0DBs&cW3WX)Y#3nie#cp)v?%LX z4FNo9B(~dZGeaEQ@QMf$sV>n{V`4$un_^s&Omnz=7gF&igidD+P`7Eu!IeA2${XSk zHsBfw^uf*5-771qo!y%@tz6ifxR&JxI->?q*tA!>Ha`(1JPCFwFuPq)V(UY+5k;pW z!|G6=W~bxb`Xa!QgyHd!B)BuCebl=f^B@%;6hiwpG^>|MsVfCfG4ui2VZt%RueKMqt3stnY{UB+V zLS|Np0K4xo()3xVXQXvSaezUrDkCi3CA2lh&3TY+UmsQt(fr%{k@djLDWV-yz2dcZ zzOUR7V*5Of%kEXMM$9T5hiuSPP?94*C=4)s7_t4g-p<>a3klk-18}#|4V|!IcH2Z) zuHA#bsKR!%iw$WMIYb!)K_XAdU~g}NRCA)g1(Br*lcGdX=8|C}%jr;lrI>>M(c-BY z$D8YrI~^sc4m65)kk%zJ-R~ZgLz*)3uL4C(!#*YI{{8M2-=`=(a-}=~gnUmi*G=xS zfvH|nI-0OZPoC>SPtob1^`_0!C9@EJ5UN;DoywSVbF@NQS;t1Jjy@`gcJz3LZ{LS# zaChkO!ca2Ws=y8feXbthv&}E}OA1pS6`QxAXu*+VC}i!U7?mG=9_G)S9Yws;UB~zp zAP7^dF6A+e8^U>e+RjOXqIgvG>xd+d;9+ zt>R2iS7J;^Bv+N0Oo zy0SVvC5P05IeBDQ>x6z?g56A&vU$W5(2~m3_%CZWg4T+n;SYO`Q0u*X0?o$Srb$=~ z529O~>y2}qFT5ZN6)&z;>`r)ln86Se8CRrV#QNK~pyhNmB3!6vXa+RI*nMkaY0vE!>!Mzs85sh9w76=ry4ZkivN!%id2 z0s!A&PN@2?Oo!4H0Di7n_3&R5OBPXMj=KIhA$YAali^rXL^F~sO)$rOxc%B;vqRls z+851fgLt8v5mHLJ;L5CYGPjv_MvmdzG|_OUrT13-RZ)WB6%ZZaKnwGY%jg8AYn>*VU z)>qb6)V^9bmkf7ZH5RW5AY{xPj84a*&D_;1GdDA2Dw?3`YC52NARho;{Y4iuJF2Fp zlUaD?%V5=)HA0oL2fnPEtRo=%9S_BJOAr^YwOR~4G_R?LGfZyVBCOwbPs|*&`{`pk zcw=P+yCiff5sbAIb$NPHd1aW^eacY-nh!En&Q-9Om2GsL6d2OuO8o@dp`wr^)#|K& zRw5E-moc|y zeeh0ffGt_|{7fWd^A24FFH(i&R7-}@lS z0fld70%>4(Y0Kf(Dg!5Df1LB&hH3*3;bTmWsA8VhIulti_CW$;T#o~RqBiThTbdU) z);D*~tZuKYH4|eNl{JV#mnz~L;`9>Ry%sdP362LBwz{Dj!<8v549_jx8ABBS(Gx>D zu5t5+0W$*dJ!PKVfLYg15tE#Xji@fv{3^&$3K~$&72}Kr!~`1%0f$xmo7qTluR39} z5K5rviwcn98~|-f%L-ae%i8y+)PN0(CJsbr_&8kj=<|K+gT7m(&UixY(&BeC?Izn6 zKuoOA{8}YCF*(VvPKBoK^g&x)qW0ZsN6t2bZrrmL!TM$c^NE@1B12|!<>ihT%jPVS^Mf>_V14?s*8|-DwWz3s1@4g zm4S-1HU>rOJH0^sD}$zF5{Yqc+I4p2!#Wdn$A1n~AA&rY55 zTw&=8o;Bc1KhGW>U}|Q)ZSNk^~jS@AEoNpu`dHd+jcOJ61 zL3_MnC;LC5%*XhYm|-_VWsM}>u}#gg}}LrP!{u0B;333QwCLnA=lYM^+U8#1~xn1kIp7k%5S zBR}_+l{j`wAsy+=eWH3*ZIKw=?=8@RWXN^$z(7h6E3WA_9@ljNW zQ5~!)GQ4wu?p=7L86ZHYoV#sApa7oL&ZK^r7rVF5#XlLx`*>3^Ll{IVZ9<{HlXRo@ z>VF-&C-_j(6OoQ%1r>^dtX|t7KI53EC!GDMq4=!B&M=*_R|4it^?J`pnb!#^jG%0X zv^ia|^3!j03=P!434a}~9>=gZP;F#Yg&QL7MFG!-z0Qk@_?~ObTc$@={B`-AXH_Gm zLneHgHP*pn1qTC@wL4-Q)o;-=*TMgJ!@v9U$lvp`+`EYYlWn=jGwx!fP6HSE23<+_ z%>-NkV@z`fnXd#;Rf$AEihRSI4A*kvT};4ZZXa{B0^-T7!!cHv-e7?P3-d_ae`!Ya z_{q>VO&@x`KcitdJG6Ri8QXuB@d>d$zLj$CXtY7~BvR@yHYNF}b^-GGmQMkz&xbzm zvn-BWtP)+xZf^FmWQiUBd_nS6&a4QLnq2`*_PG+6S_t(ONCq#ofJQ9AA-eeMHECZ@QLoJH>7)#I;5$6e>=5wBT4nUAWw@JXu`9WPukS zsg9g0zK%xk(knj8oUn5eb`CZBi*p~Q=c`7=ai&kaOpjgR#$iq1CA5N+2+;RNEOL+N z^fn;nniG;3e>9^)$NjZn)IEYuSpqTVuRS&0e4nEp6deT}-nw3>9oQ%NL&t}MyZ6`7 zYJ7!l%MldXWED+H&SR;SuJYEl;zTTE51~rwSXe_30W7#7RgdV{pV!se-uH=;)NA-Q z^5OB>ZP`0?EX85HT~cyo&HxyP;Vb-;kyTE~nq^8AuHP$Ehj@IJsE15v7z*?;Vc$we zqkP4x;a4Vv4NTR$DdKnKCp*i5C#$`$AN=2+_}_P(yPI(ha|1{OLeRd5`P%@k4XSpM z*iyoYFP>BYE6;*FrFq6#c_3O!z75PHdKG>oA0$65je_NJAxyZ@ZvEOeIj$4Oo>%f zFiWC_>ZcX~Hd3Z}A|GVQ8PKhO7s};9IIz9IMt|1zfA@qe1@G z;0?X>b=Rx+_44!eCzY-H%Cm3S3diIQ{hoJDe&aUd)?a#j`fr{%I;;$| zbk$V~`jrQjhn)+q5&@CTV?spZZ8f%LJT{KkmAJ!gL^^S~3U$yNZDWD3!a?tDE04lM zsQMFBI%`rfrpPjiBR2)DtPSA^v!V_C2s)0gmZ3>~;`Vb-i^y9epR^f%F?D7cgXKij zsWQdE2EjXf!CGY~ik4DypG-qBA(B8#(MW4Dg&o>b7Y)RjfZg(cgbFK^8qP8 zl$p9_2uap!zU&|R-(%w|lNx<|I5-AZR(l?Wap=@+ogT$mRr?;pS<(l~5!H1)(lb|3 z727Bk{5U1j@m-xwN+r_X-Wo;^DY4R@3)FkmPP>v|x*L$}f^P2d4hsy#lT`e!q|+r4 zaX|+eQF(A=5+l?}0ZR2V^fek#%YUefrC$XM%qGHLdX<2&)xR%b>vXf`;1Z-wGlm;= zqu=8?73V2-PeW{8J+DSA>txg{-4=gy%LXoQIS5RgZ)|F5VW*e|%E7tn=efUu z*n^jQVY+a204D@M#E-sJis5?9^R9<;37j)m0(c~hM5g?Rup`y3MM=}?xo3rrD^-r0 z8apkto|`r3-h$i)8fJVz|KW2t2|XEbkS)U+j==qrdl5x!FIjn&e2b9^R>K#Gu$oa} zd-!Y?QeTnWeQK%LvgR_*@*(QmFD&^IRF9MT1KhAnNGKE==Z&@h1hGC^+inK`MQr4I zY2VoU)waItzIAoWXY=O;kNjiz1{%4`vq-JnyRZ7%+|;Ed37+F!j{9*G=c_dP?RU)g z;>;(b*w6g!l*&2r9?1A1J5*{KZlU0Bj_=nGz22Wv-w(XvxTP6SLmtsxi?Rnv!37(d zN6F!BeN#4}NjQ&hBO2eLNofx+Wj?+A&$oU=FWWP^VKpd;)IoTkr^6OhpvQX0vL?{C zX`mvF*e9htr$%6A+5O?ht9hShsC&2B2rvI2!umK!N8|povj-5+`@jWisiTa4-Z0w;O(1yC++$d++wKy+I{}Xzt@4AV1sE5L>mK z(116m+kG>T+iK52Z;oeDl)L#nOH|uQvUlvNJ`!~l{4%PY2pIx*onh#vdzG!XUw!?L zHJ?s^=NiMFjS|kB-VD-hwhF(0BM>Tm6Ok&2BFLBNDZ)zRFTQ<=I<$@DVKb2hyyokH z-L=b)mnGkW{5=Y#dtBD?z^~~6IyZp(<%5y*-(rvfCge7-J8<4xVWA(RP}Vk3SLy{|#07bAjVZ-^ zwY3%l({g03n4B2XH`m9q`zutb4A*9A!@XcsEn8oaMt(U($;J_k*8JVu}KHlw9c;F_y3qNzxGZcl8@={PkJken^9ygJT|&OmYKES~PD)|6zr-UfmW`o*u*U ziaCYW3yg*DxZ(G3Oh1|-*V2gMkWw4~(Deo>$}Ax#SEGP5rq?n9J61aMo$c`jpK*#8 z`#`OtgVZCxxofU+Pv-=hufq&%)~qcn-Jcb`zr~LKzYIcRcy5RMcSh|mawPx4#@fKq z$=Jb>{y#AK-(UZ5Z~qBV({jH>pa8y~wp z(pM8#&-y&cJH?+t9A-^>1>xL<&jMvD5AO7|k995&$7chka6I8slSQwznTo%Xi|S)5 z(7iS_QypSwGv2#pn($*KCyea%w3@{3quA;XWQG!XTvqU#1lw#dXod`SclIMI2K2%g zaTSTAhEplXXgFKsD8_O~F<>ZxSyWtABwoCxJ^_JRRwP~gXsTM|I0acDNMxtzr1n;9sEH8JHUXA4vcC z{x3kaXJ?@X7+}EeI`_DfwshFxi5gtk4bcdX?1~r1xLy)>fIr|F=<}Re6}~{iPW6->roD|3v+-c$ZXoZ8sSZ zwxOT+%@$F@6RKh{QUaHLX#z{&s7qW#MM-OkP)Zh?ao@zA?Gy`y0%dnNo27ncJRRyi ziBQJCkekm}rwiS0cXqnop3Us2Of-Qaf=;`YX@M=U4jftuz0oY4I&>hPZRoz7C(c0T z#0vql&*hVar}fOM`~WDv74qlx95kK;1;sn%9u! zxRYg$H`KsLPg_R$qRA-@k|Geyp@bMjs-Qv2K#!=_IpQG8&w*A%s3-7HQz?gi&xiBI zIZVn5_Rx5ZQNb1dS`DQ?-p@)fM)?gkKX#`@VYlMDYz+T^#0Vx4xBu3ea`+l!-RW%R z?3r()Wi$Cu)%TpGQ&~eG2@$_RcubN&oh-ZxNAcUWRLOyKwbZ6m3}Z2-Qd4gsTsjYe z;05NWjdoO!4~l2j;{1f{2{gY^gsRFKTW}Ao<@6)vR7e>an>6v*j*B)7hnj(jhPsZ% zh&#u+FvXVNuSfnYdvw3JM{*(qi?cH(HV)sfD&?}ZPk3@$CPE{f$?g64@Y%B zfr(0OlXG%?ORpkhgS4>r)F^j$%{n3kTrz0k4q%iCIbzEqMdOl(NK~l-HVjKIz!6E1 zJUNx^X0(u#*pT9^YRkZ`*!I;jF?q%61e+h-=>gnI(<$=h`f*7=7&5< z7ljs2F>gz6&2^LDSJpIjNObLm#(`75x(DWI9{AG&My17#vi{E5AV~C05EXs~ZN3ek zZ@2r4d8GL9+pS8%9Ws#a8+G#3hT(RMMmx6d@3|NTnWl4+rD6R7vH}}R`S~x{euwYe!Jxd{AV)j1HY$Ln1u-yd0Y21A>iQF zkIbdUerp8NxRd$|x3oYda4@Fox1_|;5L>4RvbRi0VVi?)8#jjq_aVtu1aBwx7{y zg%I5U#+G`01TKNM&IwL2b92(_qY)2Kc4KvZUN*YBlR5CqAUQrR$S1-hu7 zLPx3)S=%}@W;!yD4@YP@Q|+CM1y(XdmFUv?_u(n0aAF=6)v6gj#FgM|*T?DXf;Bo~y&f!>;CRX`9IPSwvtK&=;wwiQ=w- zdVB^tuy7l0xc^08r9tX$Jbm4W)opR_rW8GjjhCv`GrWAkYhOK| zO=*J8MRl~*p)QNtXGn);;B=VY58vPZ^{)RcSd+9GIdWJCZYR}y0x#PGns09uYFOx6 z`IOb(*438E9d0z@wK_)fP4(xOmcLXSpHoA-X1h=j^gNJ{FOGfXJY6JedipF~N3W|K zZ8CM^oiU*8Kw&7HEX(STg0GXufR^u;dM9JO{prdGR*@>7MU8LRap{=w=yjD2|~jJMQj|f@7NG`me3h&SD=G@nw2}tF}|p7SQ~@&0O2<h4~8|M~18*l!KDIp{17AWeXWhJ~|nkN0Ikr zJYK}f%?>Cfq(}Yl#ZVXU1wWats9pnxZXha z_VG6NB4XH24gZzn1I~Gtx1?_28F<(BwM5to8e^sp#UpCNUBuS3vMbstlZ51QjR)MM z0%3EQUq=AH;M$j|ya->w;zkCON7A|P9~u8(ApgE&P^XF^HSA&tF@RBF1?{ir6jZa4 zMPt!N8b9D1oU@ieFcwyRQos-f*M{z~!!!cWmSGw*15Vh5Gvd*GR^`hy)Al)|-5si8 zJUqFJ#e|szZ!Fz{^1_HoN<~t#{XGU(kMW~Q@Y-3Rik^FFVr7>(-iX&0>gruO`cGs03sfh`(x6EI*lYXM3t^QF!w18r>*& zc=~$@?4sa=Jr+Bbp7rnbV|8|Qm7cA)ZTt1&cSh0jXq5nyo1=OgGm92tytO?RlBleU zQ~DwevVB6)Wq}zHF6SqNUFjH5AvaKK<`SrNgQhY*5_VlW6y#DpVjD&+RJr{hy`65k zdan@YJbP1hb`<6(s-{Qv0yVj)oY{AqCqBz%0`FD$%eoTUV&IJFVu&gUj9CI$tyGqi zx^L1D9yz)=EZEB;UG-GBI=G(}+CYs4^m+Hwl?#5o$lTjsPVh4zY<(lunX}(t)2|e= zXl}ys*04%A^NX+yz(j%#Su9K(q3EEpEy*mU+-L{N8g;Zv5|c3j(;-tZVbOmF@vHW~ z!?Yjl180s|)|buUNO1TF{N>#nxgL>!Oa>;X7V&V2p5EFWk0^Nj7#>*TpZXXWMt$Lk zqz8D<^rsC{f&2KVfVuc+!~5&21N0TwY?*`6=`TmI--rhx3o^q+U^Is9d%&PM9GrH=XT!wL%PA$p{mD&E9gXL^Jf!m*7a6#pmrQAQ@7Z ztzO%9q!gkSt-@MvvH2in=&w$qb?`jrpVPhI;{I(mNO#X##lVn9?>;sJ{w3$SgRueH z?aMwHw^Dhoa<`;spn5sEQn&dknN)&ykVJ%K@R&vXcZm>}i`q1VWwDL=gLpw`OC@qC zC-Giwk#62uk^N?6(F_FDxud9IxyzQXVFGJq<_N8#koE6H&ht19yWKqPVceqZX27S$ z54gz^1s2U&)Cjpx9I^d!7jxNOZ{H*7llPCCqn1p9%})qjC4N6C1`|YXQIS~WnJyX3 zM*T<93WvCYjVOVsn6;pIC(;^2Numn5_9K?x((ogeQLAGDSPN)merWbVJb>*%Y8bWg zH-=qoVF+S}%}(@zxp;RQ%8+Ee)BP}ILx}8JG+pd|TYcLrT3;KT-rer^Huyf4kCz3< z<(BBl41A6R>8NJoXd~PQ>#Th^W!UDMbH^;;aN1<#)M!&sM~eU+AvY8mMH8wXNgDpr za>gKMfJLl;c;^*0!l^^fm0O6g+z$hR+fyh95zxVPYM zh6YyTJKFhvF@^bE-DcG;)5O!)#ZgM0{n-G3kX+67i2?B52-E&$yW%5F_#OU0*lpW~ zd9bautGQXVKW^Xaru+g(WTCcIpP?D*qfyo|C;C>zS8M>A2#TObV_f7LB{Sn8w2mF& z(G?Lz8Eg&+wj9!|qsopnS;DDya4?$~E&cifb=D|M8}9lnlDALvow$Fgz6n8j?azjp zl>UC(>8Sd{*?Ze(iKK#zPd~n1Pq_b=!z&bd;AinB`ZJrItKrnRm7@k)lGcv%vPiY>nUoJ$` zBnTldsIJVY%1wiSq}nCI;{eK|;Fh6O`!nAk+l_j_ilq<$Vt=6*C0ddfZ*PCf-@8|G z$(Pjpzcl)6WwC{0bVc z5kWFTN#yeu6sqM2J|+Sajqz-#1YDq&KUxU;qHlbONFwFe29gg-ms{KR2B@ooZCV3Y zI0h)C{rJI+ptRlj^fhw9dwc3T@N?20x@O{fIvVZC-eqaIbJ03)=<_X?%SK=8A2a&# z=WFEIa_1WU;&QSli<{j%{pZW6U+c~D>$Frp0SN+?&ty6dh7qIhNbJf7SlTC{q*z8J zfkTDGP4)yenK>@sF~NE~WH2*;&|>OnRNCjC15Fkcv|leOOrf(YUX*qBtR_-R;q7}q zQF`(^^NeceDVj-VK2JRnQn-ouuvMGrG=hq#QzkoP83kyW8Cs(X#N`(C5-5l1u-u4= zG~0~cz3L6yD*sE5+r!mJ;CrDXfYbAHW;8UuXKU?&TSet**Kz1h_ht0rZglcFh*&Db zB5a|80|{Wj(IpbO1y^_~y(2|5jVvPRc)XD);$k5~_83sb$g(1hw$JE0Z*R8U+Yvk7 zqOSF*_#)PDN6(Dp^^ZPdGJ%UwnfTcLlq{_f#wQg`1{Rwe8X~zfq`;h#(5jZeHx+lM ztEiBrpnP?W>%8$=u%{nvfw73?S=|Ow&ZKxV_5Sp;CVJS|S*z!bT#Mdsu9^51=kv_F zkwdX~RyXk@aJR*#>T%)Kt^W0Rbp&v6tUEB#)ic6#AIm4Fo?AOh56sG-9KszyiGs@q z8k|654i6@Y-^U3rtFwov+;vAd92nc6KyS}am|SnQ^$x}MUlw2U$m%2v0w|JXuS>gp z{s@JB6w2t&ljoLuxldOY$0xo$U&l|W%9NsxX36h`k%E79EbZ#=c85!srGVcbG{P<@ z#MZ}Urd0|SxQ`eoR7&Plh>Hu^P9yO|!6*C0YE&(Pc08#kQ?gkR)QeeR?&Z;XKYk5) zyJ8x>36HVW1tLsYL=vsaP|v%v0me|-@#+&0`<1=<9W1R^m)YM12Nbs!wvaS*h~UsdEY>g zH>c5nil2P4WDL^`h36p; z(3yJ)EUr4MvCgOtsR-JxV)qDG7CpABaw32beZE`64sBUJI-W%7(1OV zk^{3lMg_zldJb2SgssCoczpXG;-WSl-q~$WnecUgEaq;NZx$ke8t+2KqsK7SO=F`r zelg(e{Ot5=q(ri`Y%@m}9?az;A!n_$1s<|HyEf-}~a?)n=P#v8UlxXXEn-qU(f;D_q zbLiZV-fgIgCNj>1qLRWoiR28ezY1{orP!D-xh*VKXVZLv>+}H1nM-R2&;jB{qMkyT z9#MYY07H|ru|3?`x!8%%0dA0Mg$_EYY%J5@q=bwr)ejza|GVol2@LLq%pvBTaJ{F; z$T#)o*5RY|Yv<^*AWyRaBs5pPA3-wCik}9b%Bka0`o{;+M?2Z^kK+{;>Jv)H9kbJ8Fd z;q^wmkFD`C7RTyuzZ`jjoD2~%@6E6T4kfM-NUab2xFopl#ac(!u3Mg;bFZmSRBQZe0Y&ce{nX<4fITOmNEH~C5xIfq8>6{U4TZ{ufxmJfeei|)+#|lP-NCsDfvenyL8*623 zjzf}MtaaY9UHZkT>n)8x8eEvLzMGuC?7*-K$cGwvAqGFkU4eJ`gZy|tVno_k=9~xS zc4E7TTQR}gb-07ZVC~TfCXeD+meo<4O&Ea(#Z0^_w^NASeA;JtGv0ed^-uXg-j9H!dFlyEQu4$5o=f=Q^ zCY}ZE?>XlmfmeqIkvlAt@vazqaH?T8q`34G$51VL=Y%uq@{x6t0VQzKK)_WOmS6BP ztW4Q7KheB4sZ_2#(abE~rurjT|1w@%U3Ij|mL0g(UVR^MF*4Uym}(85DdNO*(v@c% zNH`7u{WZL}m^$n8`hC8>s+aY3e491|bcgXBy*4|(&v&F9jzF-vS$IxD9Kg%{i_(53 zrazq^ylCBMp(}*9PeO-g9t39|W)ES0Km)FRN++mt`2~Mf5H?$x1m_3Mf1S&(?E)u9 zUrVMig?U=kj|$f?rd*(psUM4K^Jt6{CuOzJt`Q38rOZ1jC?+Ykp)Zmte<3>-#Yr=X zcFewMj13m|lT=QOy`XS%em?qqkH!0bzkj#{-#Y>V`HCdppQHyGW8kAR7{%#Sks-LQ zGX`;n^KBSW@l*uLC^_tL zJW>|cw4_`Z3o?GCSU<>`k?+-!vqc$Skx17YL@~B{*Y{K2Fexvli}7B=)Yr%R`=E0X zeYQ^``|AW-wVe`S#8g;QW70aWE*y^1m&_$c&+@9NG}pc<^`q;6MX1uC%`@v2J2i$sQ7{NNMLKz2MLz(qu2tV|==deWIa#L(b>40Lw zrh^?$c(+n8TKY_1ulbYUleFMz|8!}VStxEX=RehkN4x})nsqB@5{+&Zmn$Y zk3T3kaYQoeAJ$pz5WUs(L`f=geqWdOhNuOk$AlP&* zBH3E~1tC9R6`Af1wT+p6rW7Py$+isHIdnqmkNKmK;c0W|Jzd>k&@yue?yu`sTmB#9 z$pF{n%_#XAS*zk-!7jyNnkd7~7^t7)WkL!ELqCAl_Y=ky#S>4%i&C2hU#hIF4T>Qs zSgisGMkn|~6s$EWPT8bor4o0ctG?bJwYB|hv%TKV%`KGEZaO1zNV{E2g@%h+>V+hZ zCu66vs~Ty)G8pnfc)u=U`9lhI$fhE}$3zc4-MT8%$z~qacC)^|r%|K71eR#*(oC0`2Y79qogzQ&13p&r%Xu8H~cUd_fIrnt&G1|VLaE}Xzx z=Z*3ztJg)tq4(Izf^nJy6xev4BZNS|jMPM$7|@zw*%J8r4FF)lFJi6T-P7c-P_;1u z%t~}6^*9fX@}{qYLG!#^8EiN*rIi8vB&4pPY%u)3i&fYxWhpj8svL~cB*%gvV2Edg zXmL#_5R7!PrIT)nWKg&p$H<9M#@y712~?;}=SF6bE_Njw%RBGwWCp}FYNIf~M4B2y z)lgCvCDf6Ym$F(a>IA!yxTs2T)ofx-Z4y;esaD(`+YK1!s2yqhkQ@r*UP=M&b5@F% z7G5RUmJHt2vF>-v%=wSi)=T^H0ZOLkx=@bUw-a@#W-)4K5*%9 z*TH;u5|z0gi4nzjFsiJdb*twzeUNQSt>3HK3fvZ)h~akiCrmE$1!-jKQFr?>KbR}+ z<&REj8YAodUCf*WGul?F%`+kt=rwZB;ncanU}zbKDV0}#|D_R|oSj^cj*sH3vQ%8%8R ziog?&mVN2DJS3@Ti*+ukzh!9W?rgDbsQS)J9uJ`8HBcT1sJdIB?j8tjzkmqgecDPX z$v#`g5}ZZVqL&VsXb+~rzw1T2o_eliAV~Pf^)JUWRnHpmX{W7&Weqi$>}0U=*$Elm zo(E(gimEr-#Kw;JQqwx=;QTMFAd05tU*DXzP-XD$dVzaC{(Z?8M96m<9uxq8`)~E@ zzp8Js{o@dxr8ezQ_zR(@lG_ZOrM)N0FS&tS#11m%h5K) z4uLBK-@>zcGnEC3$HPD~2fh0=5HklTr#m_$nJD6l78M2J&n1erQX80|VZ^pbrBE|4 z@tr$ED56M53*9m3T%1cChd@&p+@p8mLc%Fp4Ot(`G4Rh{tl~L>5&^`J2`d%U(S>pq zBSY-=ogjH1mhhyh20_I&x(tgiTLcD34_|JBJ$!7Qr0q-TrpGWS?fm(Wx+W!<4T*83 zG|Si(6_gp;mCabRpbvBsnM(JyM&QJ<>cwjj^0pGJ?KR~I6=oSkx&36ENnDBt?MGv4 ze0g>OE$|f5hvR9@IR{Le4oZt88mbm7swT4ww1um+aXE;F^hn|=({@J*2ed()f>OZV zM%^`34NHo~$Dnot2Ph1+uw(THg^GRQe6{M`?aurcnu8I|ff)m zs6Z#G?&PHd*sr3&gsFkM{5loXWcwqY3s|7#s0F1|BoZ30feDbWX$%__y_l}Me#tJa zQyHj(E{UBaFjb1qz~F4!Cma+v#$0p043c!JcN0DUL4(%_$KGt6eNCm&gP1mc-FT{4 zux3=*frE$Mt;NLHY7dt?82Q;HTJ_oC;(&1!1q$qO;9{|;M724A(SV}4ML5sue6YWk zUm3jYy&!7xt<4bsO;^MIt-?lDNpg8Lv<&UClfW0SSmPh=yG*|V1!v2i{xH;^c$-0i zUgU%Q#BOwk!k=!Z9n^P<*@0t+&_@k&r^#M{mbjrAb_KZW@)ah|^>uP!28H`gSSUd< z-)(WU;4h45`jIO+nT*z9_34+kJo-?f)5(71;f1^sqZ(n?DkB6zbc<9)s{WaYr2XiR zvX9e;f|aqTYYa6HAaf8uBy{At7Ox}2cqM-8b0K@pnEohg#4FX<*-gtBw_wOrabGnI zI_Z-;F<`=Uq(Q1}q)j+BhzCxB{h|)2(`P)<59XTBE9bgU+rdO#WRmt?s7w>~ULn4w zw$xsZRI9B(7j{j59*!iEiiD9dw05$}RhFJ$Kn4^au#U6B^!0uJT)pl6d>cKb=l6Yo zxU?0~0m0j|l|;0%=2UB~n?Dxmr*luGsf3Ynbum$-dy*JAQHz?on$rz+sgt0MKC#v{ zq>1`8-i0l6k}^!7nnXdsC|qtl9jUJsyhtsv&hUSSqB=J@buWv0mW~61uvNgpbGuo3 zq$JCvJuZ}QEwX+!b;~exbgYsO;eWl^G*7M%lDm)PUUk0``gB;3P|>J^Kjdw&J4l=o zVWy=;Y&z5r-!V6g+6=#_bOVa zTd!8}_c!z#nEzTuS^lA-OKLi{nOqn>xlKQNg*t87E`10IaTVvvq%vCO;~rQm#cIgJ zvUgxzV`N`zwYjiCX#*||v60s$$|R%AazFL9%1b3 z7kcQ0tK_q}xN_d{3VZ=1g%V_OPEtb%p&BW8=_L?CSRVsn8hwI&RLnqOGV0ap0@K`N zfthUeR?L4i0-$$^ckV)x$e3=R+^$Rq0D9 z5u=G%un(wHXc#&aIAA?&Qk}qDQaMCiLgqUOb7bo^n0u{!qvUGCv+`x6kRXS@Qkl^5-(RKvno28?AHeJJ1RLJkQNGG!OkP0`Q z=miKuw$Inu$}6hh6`j#wd7t@ZRuE}BmIh^sQqV>Pa%@uDpRO&b*3h|vjiriy*l1p} zavQNi5JmbTnF(6(3{6W)jNq9$4W!z32knT?n?lnoY%WZ*ct3sJKi0CVRawS{_)01U zY&W~VUM1`+$|OUrz|?T`NmYv8Xis-}qSYDuQ*K;gGeykhZbV@w9cUx3$i(p5WgV-Y z#nD+LdBrv2LOTo&2A7`?Rv-pmbJ2MhT0J}NAr{1R?JG3%1NRUp_k|X#>+%urP~7MQ zz=TQ_F&xDFC9gHGsP426s7WQmN4O~^6ys|4b*qaoc2F#+Us^gG4#hH&hOqoeLhLp3 ziUKm2LO!)dYDnWdvQQ`|l~W@L$uuJp82DumXp31IY}YG@IZV2O6CGSHYbk%TGO>Q= z*f4RFK6u2vYkuSv<_#HwnGw~7$sFAZD4bQKRPU}mxF$Cb<*{}7LV&p-181`rD_@4H z<;=^8KjAMpl+HI8E2FD?VW}W13&?YK_M!!-a&nX+EJpDkWTAAxO$lrp$Rtb)=rCD- zJR;m^y&(TDR^BPfmag5>P209@+qP}2w4J%qwryjjZQHhOuQX47|6jGwuBu&C=i=PX z*5*aDh%sWs^FF=v+ic9(O)x%7!>T)#te%anKx`_)M`UP)weQ58tFko!LKFP{o}v=uRfq|))0{T53AJpKd?&X|KC`p!+&R$E|OSwS|h(D zXdI8Tm`{8#x85G+dZ)4q3=UuP7^xwR*aACqd=K5phb}pIwpkj|uW5)x~2q3Zu4d{49dOq}_LvpUnus!)9I zaN|nbqPVsxk=9g{{J7*6?Sqe?x9=Qqw2m+H`SU^gBb`IVx{i-}X?FzFq_7oL>H8F7;tn{#22#i5YT<&6~i$^^ZGo=gg=q>B;)0k7w3!R8lfzT=&S=Q z0_ZM^@vEvGPnb~W=JsI$VP-IUOUeu-KgK%&1-gF1izNh~D) z)7av4#n-=h#NLQ~)Qt;4i*Uvg9_0}hP_NV(AKt{o41Ej-1$ z9r2ijio;XdL41WmlK!org%=#2E@NW`8;r;$;N6Rpu!82U-n_NlWm7&yGiY-NxA8T5 z7OxIIefs6ouz>pevyYq~IC_Oc;0INr{eM7}KXK`~Tj^@2{jEFvDJ2cgzm^cVxa;vu z6PLrZZc(*6V(JaT_hdVVekUkcWem z*NcvBggQ{%;=8a}2h6>-gf^od*Nua2$pO8-5>E}&N{47b+6g8JQfZRF1x1d~zN}!S z!T}flxEvy1AS~pWP+ZL;wyVwX+WGK(SQ6mebt16bVvw5!Kn~2AZQ7H|7ipTbivvF3 z;Af+Rf^f4B`1|0M#sQ@c45ig-zchJQ#2HN&0VNqLC0u-QCfz@?@-m?WPU{J{YD4mV z5=EmnHR)DOnN><%8CEu_PZg`ILvoZob zz{~ z0jZoJILUwlr9dt#tdWXO@0oXDisri@w2EIDlQ4)XgyfXHN1dy-J5i`YdG)cpz|9+7O!XDfbml}LM6!jX3 z@uvIVl1q2}|4uGzzCZ5w*W6BKa{Lm1e`eZg9F+)Q5X<6Q$*%$y(Sy>uUVn;JGBnybt|10g7f+@EiYI6d`H1#~<;b63#j?$>YiR8T^`hhG-T;A;{lfOZdJp z;vF(+75@ocMxyU@etlL*H%qy!U)`&)*k_Ce;{1D8@IeY2=-qz`6ygdAp)0jJn# z?NR4%nOQM#V|B5CWvSG>(3;H<=7=>iEPM0B8&#HqG-+1+b&CH3U3TNHlK&fB#<;2c zPv|l-<{xx<%>8e4iD3%o_8;hy@IRr;uz#b=So!}mx|IL_fG(YLZ%DvTRxaFr6P)4xBet znV6vi!RQ^}eH{BA&N@SGhGo1E^NXP`W1p@Gvc*I%Ju;m3DUR=Ib{NH&dH4f|H|-$L zxX{j${y`j1c!V%(+uFAS5e%rGy_<$1ElLj?orkCF=wIJn56DW!_bwd2bXQzBboTJ( zNdWXh2aMQgX>>z{cMhs~b^Gio=%GT7Jz+u%4Env5*5YJkeQ+uCSNtuOj$Cj@ z+a$W-qM~Vn{FM$n zoHxQ+zILqq1B&%EHsAuvvE{6%14tDqgeOw`tOnTaIl7@kc-VLI$}$v`i=$azeOex` zrBfo>`P$3h9G1GB+6Cu-NRDaE>#+r;`=njcRy8Y0BMnw9N&LVCLe`_#3g_Rbiv0|c zzIlRsTpcN#$At}K!HnXgit8qt2>vlMVE13g!D1G`IGVu#0BnAGs{VJ-lIfq*c&EmM z?S>f27WyfFEv14~xKR8ecOBB~@4|#isVL$qpbRWYYYI3)rRF6Qc1@EF(K#D8o1VPS zOfrG*0yk3$OR)mjQqhTE*r`p<=SlBGGkUw0YUk*H**-nx<)6uVoY_I~K~?5GofdD^ z#QX$$uCFUweLn;!?WO2wq!46`hoSPeNc?xD2Fw-gx>kO@%OyalJ1QmHHrk!#(Q29d z6@a^AuhI|=@003~Rv+RU zwnZ4DTpjBk#L9`R+17;tO~bAh`N|7Y%iF6J260T9FrROtRg4d*0w3jSb zWPAZ|m^i?Ul8cLa`QdN68YykYGtQ)Ex4r(JWqapz3WS*O%D-=Issl0sv*i^-LjtRp zbEhEdyKn>R>P`nh+l@$?V_a2SUknO0agbpVBp{qoN7gVS2>)c!^};CLIE`ZzA9>B% z^MWa}YwNK5psZi1*Lioz9YXF|5wEs0+NnERE=KN7mpOqR+P3a_sV`riVAX34{`8JR z%X>&oYWRzEhB;4hMyUi1&If0HrA{*DmmvcmqNMYb3I)$I9CA_F<>ci#UVCzlU;*YV zej+bepW)XYW2{%$?8$tSu^?Epl77s!G8=lVJL=pQAE)tsxH`1dvc@v(eyUUWwB3+b zER@(0lryk^b0Fz=2i5*?hIeJB+!?9iX$++L#X>@I=A%;LG$GXkAWvx8eIXL>f|{x< zxSN@6+*6F30MJw$sTn=1(w70wIIoXS02Yz@ats)tTSn;?fhdPe9pC|40&CeW9F6bn zRAV5a0JeuB+R;mW3QFsHDNPJ<3oGgUyK`_OM$M^R{`uu8-?U$W5d&eK4j6{6M4ZG( zO04zy(kowuA~Fe1N?D0YzC2oOc{*C=!V=9e7g3oCwn=HOu^sHE{Eow-FK&^Vz zJ(Sfr@o@u$=YAZMgRL6BAj2rw__!j7(!F`E&9H~rzmbu9xa!=Sq;Qpj5(DpWEObH~ z@4x&e<2tbN85);=P0RN)Ct^T?8E;NU)5|dK+=JR;e2quv2Txt&Kn1Pwp()vi2M0!4NYvr0tqp9x%pzj4XX#(hq9^6L(00*LC-eY8t4hVMH2)H<)^t@~RCb>Cf`Am~EQgF-%QQ-&W_0BvFcm>pAYT&G!JX8G&-dpn< zH(^l6`*vDLtWVgKQa%=%-LxUSTMWo~BRN@oh?2(*WW=u9KLz7@LsnWc{1ohdCs8Yo zihJePnA>}k(@tjADAqTapAjmU33B-C<2!K25$clI!5Te9^7W*S*n!di_%9P^;EvJWBfN;)^^%w!|=Y5`3~gvwy$q!GBNJ`CFDvGM8fP}+?Sb98nZI0QDx&n z5-;uR&HozG2`1(CWcUtb{Mv!%eIn8Qahox?&TN`B>-?`YW)_&U?EI9%PQ)#``U;=U z=gYv+wGS2;!Ql-oucXQ%5)gLl_s12qLc?d>=R9LvYT z-h%VV)x1(!V7x7nT!GaGT&|_Sb^Nf8YclNE!}78RaE@Hw8^PAJ2Rmb0BE>E(H?3vH zoPl`fYk_@u7uqsx@uO4mdk;1vg1{pVx)UzowfdsYHc+V1YGx_CnO&I-8QwDJUtsjW z{KGe07s+m(-fm78*&c`~SKTwx9Q^9qt)+rnOiXXKJA!Jux?2r0N!&fcVl7vCets|= z3k^0Z>e|nwTah8%5BSBI80fm?hNX;S5jFz)bg6BNN8poVJMLmDot zXaq0YXrfuESKu2*o$-17Y}9Lq*%1$-!a=K)^5i37+xEhEOOVPe5FhTzlgT2tttv)s2C4g;? zX%5&n;D8a3#imz5DPo!Y!xju|i2cs3K+;}sa)I6Kr6Mj3gH;H%Z+-9>P3O zG*jYb@%UoNU-ju`tz4=-aAsd_wI#PsUUnr_N%)lgMhHFlEr(Wlw7bAR9V5!>g_f8V z-T?&x-OS$OvXM#LK$)++5;?a=r4ef%gY9qsWlzFV2kXG$Pf9iVXTKo$kF@Il99#d_ zZt?FPfQ2bbU_yl6JJ0-odH}9%Ggy*Z+fW^8&w#_Y*OII8Igm11Zg7-NQ|j5}3--TD z!Qn^f`6H=K9U0BdO@M&{qXVG}Lt_7KEZ~8lB7-rH_+i;f*k9t~!`*OX_J^7~hJ&aB zS)@rx)=0%?&tfMq8t!IGPi~{+94nF<^G}79TV-UA_h8S`XY8|>kCqw&?|Vtpd|P;$ zIsL5ld9j-682sM3W=%0v{X&D|kTGI3Sf%aMQ$Aag9fZYicXiC0<=bYa?drXb^_TMQ zsw%sc?Jpfo-`BpSedNcTpX>i$LB7B(h!EWW#dl!+XE*)Fci8{8?~rE=7Z9!P>nA{W zK%4$eWe`rXVZWX*1kiwnl}w_Mh`zd@=Ol52sN@mYDO<1V5&3Wm9*uCvHP=UH@o(Ru z_4j+DOB*kgkW42VJv7n`;S8blW!1(9omQ8{-R8!HT~Axas$oz7+#S)OC?U9|-s&;C z;-P+o(W&+9GF&jND-cqGDhbCg>VzdIZi!7}0CZGIwZW=rUcR|57^(F^alGAXiQ1+@ z1%f`V;8P^C7SIL&qCZA{I@~~R1F%m67*|XWHsDPj`~rkfPhmaXOzh3E{SW-?=gqHR zGn(M|Mf=1#*v9bbbA7?|vN;#VD^vgI4!Hl)9bDRebO%GbX(u-pxr}v73D&CRq$1M_ z&6BnbHvV(~xlH`cbFmhsHbEH^JnHAN;&F!U>_)2E$vtjebadGT-8*2GTfNz%C- zYjOeyzmT&KPE4{0yCU5u75^4iWfe`dYEmmK7T6}WaH9H3zBCx5tYB;=TGUpOt+pyJ zqRJ>4HLJCND~?HWr{iS$F&)zKu7IKD-I+|QO3NmjHy2qXQVW$|_~Z$plYvas+>K-+{$Jf;s5&bE^+MDFEk`XNrF@>mYy(_?Y+ZBk zSMkfQb&u$*vIf=uTBx$vNm3KF$Q(?P`a+T+X*1jnm+MeT*Sg=rhi_} zoHLH+3a^Kse-wDdGaL$4!C~(f7889Bx!43swqoHS&?QLh!GEJYY|e0snY@ihw%iFX zn=in-xcjZ>`Fy+AiLJ~u>9vhJ!gcRV<9#9IL#=$;Ynf7BhKX?}Evu-yNwJD4Bj z|2N&?kofcet~+4;uet-NYXM^Ed6~Y4nTpH=!=q%45!|C@Y;#SegDSmVSGgX{9n(c5 zx@Za-=Fb`FbQP~EEy<7!C@x5we~szu>*4jM%i#5I?2Nw8*Td1uPFXtyPw!3=(dxQm zwXI>{M0kMiJ)Nc+X2$j9WRcEkV$@U(M*5n67o4?kq88TFM(3aghQ|aST>t-3cWD2& z?ht0Jh=TJk-622IW>P%g)?(v!`j&a2+$ZxkE{9O$#I=QGEDut_7xZclJu;1Q>0;nJbm_kPPnA=Uw>zmzyYu4a2F~ zPbvRKIpBZU6Y{SY%%!(>>XX$x3zFu>`zP9PVU+DS2AN801p73`K z!EDuzh|8y}uu~(%8J5hbp`(lI8;|~-NIWRCV^nOWSf`m9XB*;wd4B13zi9NV&|`6l zFEUY0vCt}(?b~@fc%8^x`80@Zwj3w1Tj;FbC_%&Gcze0VwRbLdYg)6cy{-yDH|tXT-}QJXyN;n7Wt?3YMJc90v6qxH?! z&P~_yGFG0bfvK_MpZhdSugib@?c1i+qq(K?>C8jNLi_d?d_+H6zdEPpeI%>a&^Lrn zcEKd70XaNAilKyNwOou@rDpN-x)zHlZ=D1v1f2%a?*v&ypq`?kbDZEIf@{Lc!O{W6 z)3O|N8bw4P-V}2B*EIaDAP~&`0RbQ!Qr9cUo=u+J1QB(86#R&bN3%pE z)x-jnWzXbA{ceONW%?JmYA#*R^a36j}><#~h z9zu!C5s%K6=q!z|^#wlEx2$L$7DrG1({9=h}L$vwta>t`0i0Vdk{2sx*v?1PgEd^^6+f&1T&zdW9>p3reh z-nSa$t+`2{6>BlRsLb<1?~cXm{4fH(0l`VCBFRvJekExMQt54G>1XYHpcD|nD=~hk zD*1=rsi;I&jzQBn#0#66ETO6JbZPBW&ZM9dGWDYocD59btmJz8dN=qmzr-M9Jm@Dd z{pC$?M>db%aJw?H-&$w0Xy7_~kZBqFI@o9k^G1L2Wv&!K`7`W^EE&C#C8$KqM&7yZ zuX}5)u71KkG0~80wAu5y^L;nr`|2CPudi3t<6GhVmf(R~xMKbH1cIVJkzB`@%B2@x zLl4a(rx&qo55i!plYd@Ks9pj*l|PhPADHx%?Dc+Vz%2F})7Ki``w=l!VKU4Q9EiF= za-qmg1W5vc*OPz!B$ZyC|7+kJ6$gnCriC#+X#MqB44m5`*1@7h>H?CKZLVc-Fpes1xH z-tFCd>cus2~}t?2}ij5*w&tuJNc9Gfg}}# z9fJ6ah%fezDxd?>lP6c86Y0je{%lZzd)xTaE=50|67Hx3FnDd?6k0@T+OBbkEXUn7 z^;RzFxiG+Xs3IRc{e3vbMG5n?w+1%Y^iZB3E-SwVe#_5J@~E33zrYu}TyW*$#V@pA z$U?uC%Q)eZiBagzK0D6_QM)T#0!>$J%mRMbQODpQf&1GQ$cc}mZq4oJk;W>!Ou|Zo zAkl(`4)OG**5Tf$Q!C@Lr6Q_Kg4*n$+RPAGWt{IrHWiH0GdkZsxdGz}lQvcK=VPe0 z<^|gNMoN?A`A^_yTuv?O0{Ci^XxNju{vG_%ey`QB%iRK@?ZBa3fAGezo1w9B*R>Pi&FUio;};(D>49R%frPOugyD{B^KeG zo#j1E#}8y(1qlCf1gyc++t82kt-SH{~V>tV19E&g;z&63t^jeAF8 z_%jUnU2tU3fvqZ#(b~s6gIV{k4>Xc{?Gm!*v8IB15zMOshIaIA)2;$^zk1*Uvnjwt z<%aStvyTC!w$m?zOb?>JyY_~_CoHs*-#c-^S?56u-Z+?4ekJ?CDw4a;7y#4Ze&|F4 zV-q>-kI8t`_lCF)4hJBIFp5 z9J@6OMB>R7lT1&s*ebCA1kfoGj$(pL$I{Ibno|o)9k;iLfli~#5sSauzyBaZ;Yk8a zX*rNV1I2q6vH+7A^$Hf98}t)lt04My3rKQKY(ykju!|)fM`1%!P@q6`&=$Vs9Jcre zYBvm4k`WBo;pZ35H3$^hJnGb6lz9?-Y|AQ5LU;K)ZxMr zjyp5(5_5o*OvE6;${4XI$)KW7+GNcbHrMYCmtWlI$@^mbwuqEe?e@1mTaPBZ9XDCj zRK=w#%lwWgU z_jOAYV$vxtiAIU7#!+gjgrUh~(%4<-BvxQVYN7h-=?1TAhb$~BaFWL89dw0146C~2 zXN?mHTDmDGm8}4&QHsPX35OOHyTolm?O+{V zK&28%5K!0~P{vy%{h}udhmE{iMi}vHAy|{R9rMKh+Z8@IJjOUbKB_u)o`Te35P?u9 zm5zJ3dRL1}@l_Y^L+7+G)dQBW5PvSq)F?!nRUZtvCawUh$bZ*% zmNqA$vze6@0~DHvDat6|yOCEG1Y23LWOTRRjA6*1sP3;ycr&@Ens>L^nQg4@4=X~? zl&YvjGNmXI2cwh5*D%Sn4LDzY#zZUrcS~Bq;@3unw7@}|2Pe5LAmT!*QXiDYAZTM& z_e7iurf|%P->{QYIp#HBUv~C2;9YRe&fmyh+ks}A=&96375oG!R;CWME1sO(7}!WA zItr4Nlo!oJsD<<`-d>>exSZ<`q>_i<;dV1qKNHf0Y-7$cEaTxT!?g|n3)FO^pN2N) z#mh1UXD}qx*F?~3@6{AsDh>0B-1@EOr0nS)V&UPflA9NR8o-V%(W8~JUafc`J3;L_ zn=T?=FXz@LpeD&TU{&rGHQ-~PRmNdWHeN4?!OGR@-3ZU4~pgC3_NVtWlw3D zb`Yc*i$;p9SX30+Pr*d1T_uG<6weH6EG0M%DX`1^Nfxc&oF-TsX&9I_*$Z&BD35*@ z24YRjy|@*Tmrn(B@l4Pg}LDq>$(8O{{E)YDJKm+C-!2C7v~jXW8%Z zzy47Bs*yjv+0j-BUt`NOY)@}g<~x6)FHcKL6OmNJ3&SU(KDjFWRGCIRE9|VlF-8zV zZg*S;{7gy^{-USh5+omPLiPFbdy8wr(!FY4bv9kfal$O26?-6~%mTaO?yk9yE8ew9 zB=XRgy-BMfbawmC6*6>Bj6L9L%PQV*JHLT=+S1y{o?}zF`_wi2lyK40hQkmnu@2gS z_JAvS>FZpnq9;WnSErOZl~7POUtY5mb_@*mR*@ckfza_O1h2ps-+J;~h=P?3Zfftt znNe)RQsz#acN|#MC;&E!CU?Nd{RRUOO)COo6cIE?Y7?sSzT{0Z1VsF8Orb0|>OykA zFeR>x;t}2ct%4=}9RT?T=y)9&JBP*~t3#?Uq@QOay)z|#YIRuCmR)wd{bA)ji)o_= z{rl%%KZ_T4idOz{FB5zo|GMjy<845mz2aiVS7atCHJ@5;9ks72mUmYe@o1S{Z*yi@ zyc)z(8K})_z8=*?6Q0|5aNJjwJ6D{p4EuAm3x3C3hMo1+)-h9qjyK4zMu)P#Xw+Z7 zpCb@EQ(SYu^+0+Z$6YR^iSxQa=qWvZUkUAn+#ah8<{>YkG)OQTZ(hq|D!^s7QYwOwh89b`zX75&iGz`qMmDgq zPXy;)m|y0eq!BXaLKD)wI)pn_Zf0$xSZ@R9C4@>F&8ZKVIo(Mwjq;SApPSWrU#*~| z$Px-o=*cq#lw8cKxaPS-P&;N=iL9s8m8 zsRw$D!6kenH>#hMGN2rqR=HGEvnp(mIh`#apAJ2LrL=l#f~^e;r)9`RiN#!MzM!p_ zPr8wdVyQaBu+s@zF!2DRPlp;%?)i>(Te8)vkeqQS&3LLrrhh9=G7(~BsNILE<>| zjP+kQV`?dcf1HW^2P=Re>Q}8Yr7HYJNpVehX5WQMR*E#mGDt^gxhvv zrDq=@NPK~wgo~4Mv~}4X>Aj(;=%e7T$fn@Hb*73G_*6$|&2H*DuZ>!ZgF3YZUF4}D zFbGn;>bzE1KblTWVlD2vSv+ID1ne8bWMTPZR|!kr3R|}n9=HH$8)q}85J(I)2G3{? zUJds~eeN~=ORvtwt#H?w>jn%Nn1X}Idv^=QfB-J)TsM&W*JCL7NO`sOa~c0CnDhRn zk#Q)ec$i%fQ~{h9@C|D5+pbUWZs3{&GD|q{?;HRkOG-pRs;sVlvM@y;sMz$q!u?~4 zqB9J0Bpt)EGxcH+)L{<6*Udrt_OajTYYMrBS*BrH5az7nai=*)0H@ z{PNFn?_sF(n>@8+I!@YdW7`IIGS+HYyf)n{8hUjr2TXW96e42T^o&!DUX74@s&zxS zK$6elE9@SQkzrh5oy|%iXjc^!;odyFHObWH949U8%sp)u&q9U-2+N?Ssy8rJje>5_ z6h=ro6`e<+Q%975-e7)(Bb6TQ{ULk};Y@osB-5V$-$LLxI!nX|HB!DqSJvhgFP*S9 zg70(S7pE^^3-4Q?d9cJBYDGw@j4rDG`B!gk6I~#n1W}I4g69KNU)qc#jmXQF{T>@3$`MNs9bmwOlmd&1{4L<{9^Jwbo)9Y6O zWR``($N0YTf8S2*eAev63zPA39IG=B=L-lJ(CuGiR(Zwa$UHA?14JldunN$%8-TUn zO8DnF+T<^W4@)EDOSV+%&V|9ak+xm_Viv+B_wLz7o)b{5G?u$VrsxzZ%&(mu`rx7H92LeQ}8Y54L z;j3&BDIjgLjJ5hYVoAky#MCpo5!K3AGsWslaE)()on4CfomoN=vqwHD0mVzHLT-#H z@1!MBz>pl^HwlEpCaFEm2rM;UHx=kKxJUBUC=-(y<%!1oY)=?&P7dfr!QhttH%9YVCSL8nZugC$sf!x0JtS+f@?3Fd0W zvL+6Tr1*dZdrZY@CC`DrAxqA~a0sfWd%dqPU-4D{QMK9G0{lUT z#Zp{l)WKeVO4t>nCiVjJZ*SMSO7;1Bo~JIB&P^4^Hjr&7Mo;vF`zq}hs3k1ktvN@w z7*Gm+7E$IhpY5hxtsC{PfX_s4OsH{)8)|uK5Bv2sqH1|#uEA!MMFTlZW-O>`L(HMM z@s!zD36sd0901(~@B&ynPfTC_~qY8LlCq_#6+{p|z^2sZoi(u?!F+{tWx?VIJ{ zEF!NQ(4{r;8VIPTGa+rc}u>q25P>VDwz#;Bp zT7D7J%ZxY_z!3J*kk%rpRETgPRU@x~V-7kE2Caf#z-u0mj!Uai>@7iqxjl26A{aIy zhQW5iV3M{vUDG><=wnjpf+c2AtPVo(LHd!o&IyZc(j-Q=LXM8l^ANt7M=q zH4%e(xH;_{piX2{EL!6C$O@(l)_u}g$_|f3!nkZ7Ab_;&|9IA?xf@$0lShj9frD23agqGb z(|3!ad9HXh<2_91zVuqcx?qYFq@@CCsVd^4G$U0GnjORY5Jqqua}@!)*) zW1RyX2G21h$w;c;9&3y9e> zf(w&o}4Bo2E{LXx5`& zsY7)1i!TNVgNrbCi15MwWVr+A#q0KM#6da@&Ttm@%$b2R)N7!z-sIHzdB@S(`RSUa zhr?HHDtlQ#P%GRc)V2NBYtQ$`%J`#Cn>ObTScbq_7?Q7i83DjlgyxvA-wYror8U2`O@LAi7xVGz zU|xCrOjdbe)1cyFd`ZEVdc(bJ6=!>ckVbGO^0aV*wEBDLq!tHCdAL8J$#UI-nQ)#_V%pMskOY{rRH7w9 zj5WlRdQFn>1VQ5bCCDYRgSe`=fe&mE$1wOoQMGgxw}(p&c5w5e4)mZBje$e0b^2n` zt%>DEm=qfE%J^(uslb!=6x7pbYH4@4Nr*-EtOdl(k!-{|nC!{`S6n&35Fj0M6)=!V z`iu~bAYLfXTq0(58IDw?`UX!aOI0{ zYQC@G2{D#5WNVogow@~?7M2071^s$@hd1ifGD%ulMDSIJ5MHE2ip0S~>~vTcnUD3oEus5gL19453j#H7aV;MPWJ z6XR1NH1(+Sd^^jsbhm}7G_WVrMwRlR75$8k}wcs za(z5gCu}5+apkH?3g$j#U-A}9&x#|19RZPZQK$cD3x!LExE+zoMz`#g-4t)^aZ5;X z6+>RoP4qFl$+Eegxx)+$b8((6ck+JV{Ks*Eo8^9UgDhgi^}O2j%&c}_@S}p0mG)nF z__kxW&_WNdFDxJDRFU*#*~G=Z)g(k2H`rH{zq|SKcFLahhpG9 zHRZQTxNIy|cadSxOE{^dQ(zXuawcQ|ZHyrLD%FfIclj!;^(s|oBHh-;$%gCrq z2spKQLBU5y4d8R>P22%Y1O@syAh0|fR#pWV;J!33sy}5@Qqaah0g6+7`UL?TBCn=N zswsda!K~&N@|^4Da2O4qQ~p>U>Z9yq@vqQ0AXh9OAV>547^+Qon^tgsIL_1np7kMb zGovv0ZLY&{b;?r)s4t(d96SK}*L74d6$Yyfi<<4jXICCp)@rt>wNqS+-!i7cAeDB8 zTs9ApO3!zx|DkR0Hq{AoLEr=}w5;z7%WDGVk*CI7Q!W5)hK(h&7S7^yIn z?0)Ep_0<4OaOr>MKtzQ>?UJUtDh zw`|>q3vE+pWUD3wzHFozM5dYA-;|v@to2GztG%w5u0-IX$_hkHp^z^B93~vMDQ zbM5&XU3i{Fwy~BLAM?%>^i|{4T3J*N{j|EL(raT*HVD_`b zs^cM03e)e=*~#Q}OFGArxlQ=la=9k;LobyZb7u>DB6b+)8VctCfMv4F@4}z{k6(G> zU3%<}SXo{C&FAUs{i-x&pQ57EMx;7Baa#CYR#Jmm$0rS1DHNZvQ1rAvBZeY;FV|`V zu|>iXKH;Q^8ABiyHc=XmCLGM;6J_imW+x*dX~l&t)h+(0lfG;GQ#rY7Rs`Jhd5V;g z*`5$=e9kptfQd0e0+uBOulDkaXtRr5i2TRGN1)xGDJ zgGwkbLmZ>sQ}v=~kRuK0h5#;@RLnPQ-kB5)_Pi@ki+6F~BXd~n)x+1mvCun9j!^Dao!`qqHOz6#&KHW^eZHvZX*g##NY zwhUqwpM@5(RL?HfXJAFnDG*_znE4=0kvgd8d26(EM&ee@9u=IkV0Mv7NQ!aDVImM6 zen5@d{vTgBO>`1N1po&ejfqSaDq#G;3qmee?v_oy+5gA?3KP zK|lnp1_ZFP>>=9@Xl6KJv|g2(G!w=;3{x2b`p8^LaDyho$q*tU1vjdZLJA7L9<{3j z?uCK45h2&00qy=22QT>vNe3*{;p2?RwbTm4LSIG(wc^PVl-w<~eg#k{@wL+oh6vS_ z_kyMi=B12Ah`J=d+fK1$?0`yPZ@NdZTW@4X{L%!X5%SDu1Gr|w zO%-l*mnWHMRQr6UWmu~j{9mDEdhuF$ADFm)f1LI)avX`NgWJ9{aUggFM}{F`y3xuR zlGJRp(@BWsnc|g;kF~qWsl^6(;9tqMPQ#m9c;9{mlUduey<&JOu~=7~V_OaohSXf3 z?{&jOS8I~Ugk$AFOPPUqn$!!!44axaM0VT(;c9}$ogZ4&tnGbSne}=K8G?yr+Tw#@ z2V!C@4z2d7%SR%!U61(QUc)mGXM_a;)+PlfM? ze*6z4RBE3eyX4w!hTq{FHVlwFXMxr7`vIA>n9;5WP~i%cs3-_io9zf}?dNHtr9@y% z0NNF3t+hv3LV1e`!Kx+tg`5wenq0`!#y~HIKt}WcY?Y>fue#a+yX1bscEiyth5~-_ z(>Fnr1(kvbrzY{skrk{0=@c=B_@e_%M`#(6pDn@wY~MVGm=Y}dL(8_^?dH)aS*yTE zBkb28tHKKZ*EU2pipoB+{wz=lSdv&VXs0_Enz&dZRTh{D>!H4k#!t^MelnebP*NF{ z)(M0gZLN&jM;Pn6EcgeZUq!L5DK$Nj>a3Bu@size~qU0+8eeXgVNYp!>U2 zm)h2p*3J|h-Tt9Ni*R=#mdURLgP#ms0|(_8yxGVEn83DYObw{h`=DZZfRBcbzLD^t zgm#I_VnmJDw6}!VI+;MEag<2#m@Z+c6%jClk72LP8lxis!j@rZByU2tfD0G0z$^Ca z8S&WcU@(j+1;$JpQGvfS^QOh&6hl>o>#pm~wocKJYc|cpsstl2sxle`k|s;6N~LBh{6Fpe?Aqq7DaOkw@Fmv9n+`@N&Jaq*5QEV_6DE0 zdbvoYoTE$upZqA;BsB@Q^&LR5&4O(?xbRO}1;kreblL?t@{rt%K?j7j%PeyHfni%+ z8)x7R0^8yNvxHWbpQB5kD;7or_YTa;ka21;sH`D`bE9EM0m(U_1}uoBOF7WMQ>Z`y zsODyr$bkUz{mDWlf`D#e{>EuhdB9_zP`nZMKNWWG~5U9%J56jke^b@DTuxa zc<}gW|9YE7!X9^G!_63A*LX2dJFxjpt`i%ZLsPR?51X)jb~~Ur~$KzS8lbD307s(5X~DEc8}k<$bmVx!w|DpsoqwniX^> z&WsxnEGaNQ5IypppKY3L#NA9JN4z}}G8{G*y}O=E!=ChAlUJ9C(=sJnOQurF^c&Zh zuHpaT>l~OfTi7)nCvR-qwr$(CI_a1l+qOGacWm3XZQGjc{S9hr&YYjHs#dLaKe{fU z4%2&(yq#GF{6OgOt~9rgjiA7f3_75sZj5n<)MQ}E?NFCSfWzzheYlOO{E}$`|6%M{ z*ZJww*i7>l!Ydw+D9oTJqV?L|B<{&rc5=k+i;L zlC-h#3i&_~U4va`pH~vr$%##@c%UWCbDU%$0b^jJ1an|We)_ne6vA0BW6(+l>`hnB zkP5JZ8(=TiA`8Moz|-M$nLT(At<&qXzPsVtRiCS~K2nB3sHS2n6@6)Te$1LtGvD)* za^+JE#9oTh#{PK`L5C`H|N3ReW-4_<6^v;$gaoCiI5o7aSdr9r?%wh$y-9J|QqNN` z7(!)aS+Bb$IFiwQSv66BrAPBq(EW1xabIdZ*;C?Ot!zQq)NFHN(y}ntX z1}!v!*z1Q94{RHdznWme7`Bo4=kJRpNceE;jv7AxYuA!~r;}(E<8Y0w_%(aU^`!zL z2F#>u5oI%GMIJ(5QVJ@C%`;Yq-zGi+&mudf()Y^o+cMDFvgme z{-hEBv#S5Ut8PxA;t}o47*E=JT;dD9X_1sbnz=e4+ME$%Du-*xjxodE*Q~*z00f*? zIh;dj-mne-H+|j1Tr`r?mc5v0MXc|-&MB|wd<YDUy)*rat;$MU zpVte!`9z98nM-G>JImn^qkQcxp%{NBE*hap8ER}i?`AtEEGk!xoFWT~n_%$Zmdw|@ zSnu(FO>sO$X5K~KW&U11#Lp46vDMVrnc!bCAdlC`| zTb3xJ=N}2HvxN>}j?+uWw|Jik@@^4}oXWF&;qQwfjwc*#hd>R~cUX!bRrkXv?bjiJ z(lx|HXQcv-9W-W9M^qxb*-(G1AFrF}XIz3%N+R3+fh4+>i->1{V9g!w9>aBF3JG9c z%mgBkO2MV`$uZ*_JJZ=8jpj;+ z^ijMSr6tdE+NV~_4E7sfxzXNuH?rnu0I}dYE3Q=HEZ8Fl37v5Ul!vAmmhCH77X;n( zcQI`TG)t=cA$I28N4kINL+UmOXhz1Qs9sEL^s5b?8vuZw+^@D&6Su}Sxy)b3ol){e zEGd!oe%ecf>fcf28zSkB9wbgFxJqJG#XbF@PO{iZ?C{hBKe!|dJSlgaF*5>X6JOGG z4*(&l7HutI#1?IRA7j-k>T+rXNF=M#uGacPi&p}HeCgDX{9S=n`)gIVTHgG8OhPZs zsKX$K>q#YyBr(MjJ4o&2<~4&&L(T0TIB57eSkEJ{)GYgV3okl&v$D;KRyEtSu){i< zZN7W`_u#5c093RX%FjPFh=NFuNTC?C1T%O>r#DDANfzA|O3|0QVIbn+5S_q524V*T z@#$gM*p#1=c2WdLi^IP;$og3|ztv@ZFz9mbm#Smymsold()-7eQG`K|)Z~IF0iMWK z;BYch6feB^as3Y=@A$V;HU-A+!_m;Zjy`-_LVHUp9gXtANs>ZB=;_mOLIofv`IhKw z+g52-xmI)*?~<5kU<gHdf-vgR)8<{jNb*hJ-8|(pULkj!em*&@ z!E*h3yNDHr6fZV?(HBA!#~VP)jzv+3NP@3bc=Zy(ZC6|0_6iUk#yAqF)c0xhX*q3F zD#>(X68?(-XL(u!hUXcIL%pau-k^>ed!?lyW$d%i(q%%A7?xtyxU3)}>pX#ZfuPQPNf7jW#@=H^ zkhA~30W`Xh|1g+bgFRKgz))@$7C>>ov;l|*gOe*CSLp38JIJV1zC9UpjROEa)269L z0>?k2JsC}!WxG$whZ;=-BxN?G$hu`V#TT#&H9Kt~!?Wgmw+ywJVZGXa2DZ@+Tj$I7 z6RawEhUQ(!>-a*wyAf=0iD_xs!mV4hx@#`)7InBH8sjm69qGL0dveFxr2_-ZRnG|z zH$sXkcf2cCtO?a9YXZ{)8^kQ~j$)R*$6X2I9p31MsoM2&+EXY_U3vl$AUzaE>{;$z zJ*UBS9>~=RZKZYFuUS5F=-+{|AEtjs_{hSp38}aq=;C)bK;54pULsHpU2|XBglJ6N zU%sF|Aa6_u24==K{8r{CQZLf`mPkRLS0V?tm*P2#)*J>e0;>hG5##X#E%`Ubsck(g zJ37V;{TO23r7bi`-}tm57H-j-`7oOESyUbMxEMNAL>|)sTfO`uQtX5*Ubv_;xQgG8 zykdMSi5rG2qw?=x?hj;~p|s(4y(KlBiLSI3-85TKO~fW33|N=h>nX)u=f+=$)$FdF zy~`T;DDa!rHt}^D!V(XQleuN-cib1VA_Roljt8@`hwJCrGimnGXpQ8;q~P;avX<`7 zvv_#u{?`|`yKneWE8jPW0>ojmendp-!5&6=rx@iyw|iWSqB@kSng@%>*-=%2Pl-?? zr?0Isi-tu^dLu!nh0gP>%-JE;h`3K&;&Y>_wzfR?snq4vzdJb&9^_#Q*|Dq_oRHtN z>uf{YsUog>jT`1Y;CiOOr_3Fd$(c%yiEHqs+2F+8L*ep%i7UdC)0*a0&4B5PSi=8= z@T6zAj-cM-td6tKMvZS0Y+ZK%K?5cs1rat{=}YfE5o04g%|n02id_mk_m)7@co-pR zx0xFWJbp@5t3d{g?6{GczzwBAIHlU!Qrs5524S%FK5Q3$y|RNg-_xIZvooM{{>bgk$}@ z+(L>mI8pxw#U~#P) zF;Nqqhjs&T@|!!2DF`8D-)vITMR!`G5czsw7l~>97iNcEF$oI4VC$Y92qkZKaJ48LoV?rQH%>3a8V934)C%HVfghk; z!%pfB>(>-`BDOkb-S@n?%(a`0Usk=%sR9y=86s71E{>8QgkFJ--rshuG82@7<|#%d z=sug@t)^LYp6D^DKOG?zsP||n)7U<|_g6y!CTnYPLWN+g2NL-N{R0hAXMy}NnDYtf zjxmD7vpoPauaXh^eulY^vQ^@yIY>*K=u{SkUMN}=k$b+LQUyEi8s5Da;#7myWH53AqfyzGWB0KTNzdL3d=VF-9x?uTwI^Ps`b3Xjf@Gl{7V z^7<*y){Bf{d3uYseG6aN`w-9v&Wu6=B~!0Tn}%I_1XZxDBTv5rKR4kg?_LvZ>D-&C zG`h#$Btj9g5gBkUDOm1Mk=uu#UQtir+?$oj<<|zLlGewZ021?u6;h-JwXFct!_9?V<$lb zJ`jUzrj!g+R&|#3PpoYbCVhkuO&itxn*{9EEgl6MFKF}}N5sQ}=x>jv+EzMU0m7A1 zS+K)uh9KDw3cruM`U4-ApfZo6?G7KF_PUM9i3Dkl>9@5)3lD@~VpsS4pLsqf8LbFI zt{eXuW?b@7Be>wc@qX)O1Rwn&K_p28m=?luiz2Ub2yY5S!t~YIpe#Ip>I<9*D64jz zP-0oQh7BxvH~9ErQ^aNgQDbHug;&y)W}36iB5Fj%p)e}MB0rH9pC zDI+a$^YCoE_>sy^0}W%ZyR9%7ajGq{CNR=hI$6M!B`jRx7dtS(kmg{mwrTVJXKfm|ja%o6|ukVSI})0>*ws{A4!sN};k-?t_L(aBO3 zC{p`5xq^A>NbP29PdZ#RYrViC*SzAug_G06GEb7P-x#D&M2Y^*FY3RCF4XS5f1%TN zgpHqGO&Pti9<=T^=EZpVHGk|0x{Nm zGnBnlguncktyjT`%6TsdCHdymJ0)*EV8e5&$E%Vz83;+9*4ID0ye&Xt9ZUZT7h5Qm z#-C&?Ejv#i#${N}VN@pR82Vkh`u3xjWS8>{A(|0wKE=ZQXd0?;7!0!>MrR9>cXz{q zDN5p5n1s?^Lp@E<8lP;?gj#kvnf=4c-IRX^sgxw6uUVXJz&>FLI94!L=uZ}vj_HYH z>MREV33}8K&NUP@L?pbn9K?0d??bIa?42-xDKLR0*l~9s$-Y5=Js5Q$dMSNEQrI|B zgs5_3pR-dpl0GA_3`T0lPDK=(h*!{-n*{`lR~vwjsD3T~P7-rISC@BQ^=i5u3EJrD z9F@Qb*3*x~c>|0@Nu&)Ll9Tw@m|#214)_qW!*hh!*g`$q8i@Kfz>uEP_~V-E7-Oiagv*-T^J5+yCg52XSCXsa)Jh7TYry_k)t7}SUhKbtWGHLM~psZsub-u zN%J@atDoGl5b<|!L=p_)HTSR>aGF9|&8P$BdwrE<(~I;YUD$x8Oa+*(%*z%;GOfJn zu;xWECP%tXW#u-nYc}r29FbfCH?JIyWdf*r8=7OICdcCJ?IQ*VX06xqAOhaenZQE_ zn4oebeRv()*dcl>%;SlO;92nb%o5g5p3u_S?-Iz;buzY)X5N^AiC{5R)v~7LM8^L4 zJ(x{E9)s);I;OPn%u^fkNM?mkuozy31vcH;ZZE5(ac%ZWBz_cp4?Cte6 z68Dd`wQv$Vz7Xnc0M4V)_`MO9E=adnJYLs z;nHR9h+dxW6|D3y##_ptEj338E8|$PeMd<(Ey)VY;iMw{w!fqYtq&`625)8(4<05? zttcyZsCo^v5}KpXz3xoqAECjIzxjmR_Op&xLy#hh6jrRTUoQ6p3$GI#RT_VAbWIDw zQ5R7Wj<;b?>cY-)DHKvQ+(D%eUOc=qUuF3Wp00$8wkM9xK0EY3o?dPpAx=lQj38Qx z(^x_Isa)Mxcl(z6jI*j3;#UPoI<#T@IT0XFbTVzxw z*pP}WYs-~L$fJ^$>io_*GtS`*;N}#sqvTXsz2F#9RiX_b2!Fa)g;tvOLSAbLtx59@%y4Mo>J6G2wYCy9 zrKp6gZuB#30iQiuRQZ;{=jhlGxk_7Z%O$?Bd!L&oavrXQ>&P|wn*hwtI1#j-(5&#< zY|Y?5VqJo&P#Dm>GnrCYnO4MSy1bi|KYr=x!CqM%d%k6GBgrqvK05-uvAv zUly4X>Xp;xc3jpc@C8|1inHiURqpq$->%Y9rB{#(Pl>-9;T80J!!v5a?i2qwx&h#&dJWE~2ZkH3)$Kc18 zh`D-(pqLZztYFDWSnxD4l3`+!YmWF2`|b?Vn4cnR9}k{c_EOLy8h5Az{GVR*TQ4zo zogL&g^+HKT3EH)lmbF2%akTcW_4{nG^gOlq7mrf{wpo4-qHm-Jln1f_CRBC%Xh$mz z<+b*~34T-ncq${(U1>?=WKkse_|_hvN_Mu6GIC(~gWYpBK5jYYBoJFsOJw_E#MX6T zSjlGjZEc{LO4W#6zrePi!7M2SdUdo=@njaLOrji;ogFvoLLtkKG|><#KZg^(QvB6A z$z)8jh-143s%I05h+_8oe#h#+d|o{k$L?xoXx_q>DAclI{5sWlfvs4uNzX8M9dD%N z)2!Vawiuu~EBJve?gmK*NB4`hUeE1xagb!{>C)!=q|vD2 zQ%W^BA&u(t{wCDt1xQM|zB4%%X41bfPUH9f)U5*O8;3Q-vq?I6; zm3)UEJY&|Ti3jgv`{L5io;CJJSS9M#d*Ftc%0BNi5;x*5*!l|C ze)a9(!tB5dgXx{Yad;POR=^tfa~y_Yc?T?OcPXFREGRJ9aAHW^6*VueE*36Su`ad( zEHXAbVE>c0ru4jOnR-Fnx9bQQ{~9F@g}ER|ln|VvGVq-j|9Ma3s{p({e%o@Qs|nBZ zP~M_p%Jmj@B5+0e{_3c;h{Jgx?Irq7y&|MIt(R6J<7u$LqeECvDMzbYC|*$EFl8N; z?&pXb0-u{APvi&Lp+Ohzi$=%H&+OnU$QAZ;&|07UemppIOyRn@Z7y^yAPYf}r%qT; zlc~zATlL7)+A}lj3gcg~yWZqXS=sC|-oh-xPH<|ZWss{W1g5j<{20>dM4+hPXK8Oebwg6|$j4`u=9sOUGcFY? ztyb)A9SE;Sz)M2e!TQidAat%HkGX26^hmN6$U zwkueKrU_^XWGQNXn|oap1r%C|w*G%awCZSK^7{4fID@m<~x% zv)~?lzdnj`R78fK=JA$oE0nLCni)lp29o#ze>IxzktH|Ki{_@l4Rv_)os@hylCz za{RYm!ackRdd6Q`DAEvX)kPqSSWg9~BZ0|QShK-p_Je_=MwG|9 zm>dzZ!EeH%E_Q$54;0XZa&*r`7P&*Iici{kIvM(9zyR*QF4IfYf0s1<*J4N8X1{*@ zZ&zjd70dUJ{GI=}9e*tEAwr^U!PH>HsC>H} zQ)dGiaW^Ip20wuDS53^0??HXf2|}c|2oC>oJH|SFyB(*9)I?hHF5G`KKDjbBtq~Y~ z^U_~?rs0Po2yn#+%YA&A!M=Iv6GtHDt3+`;_?!hy!LFXXwQtQy_~7nQfhJjs#c#BXB6Fk zyB+7s_iGd!M5KH)Y%eSLSqd#tR{Gl&7CMSCjmenOnzQ7sxC4N zrB->GjE6w?P=1@Vevp$woVkdqggt`A<^%SeP+$+-BqD-c;n@X3l1){CrSUlul5Eh! zjH;0(eun06p1q$oT>@tQ<(TNRap{UZNP;8nMbyQnJSN@T?WFH>$kfdrQPW&NW>>=l z=lAQz4ch3_^LiHj{a~ZKXfhq`8+rKcH22MfHlexdK YvD>Sz(I`jq7vd3nZ0=1PCXLei&nhG(7e z5J`*{8odJoA@DEv2#v8M+%7Q3%UZA0bxXeD_KqiQD^|)}cn}&hu>7^Mhm43lMi*Tx zR4(hS9$;?({#P+*#%yh$%S3}zE8k5Y)Yv&swJ`&b4B}HF#6Fw=Dj&>l@s>;@iZWMr zmTX}1d9$T)on(JJN}IT2+VCuwQt0KN>pW3p_soWh=m~jPdpdG6^fXKAQbMl?SZ!zM z{KIy4VA3@_s*-%78gzozCqb`)9Dz^5XYaRIyWZfI*40?VeO<09+*m!*5LS^VA& zM^OSRHZGphzKrk37Qd$50}XURZ2GCW0{vro9FO#! zt#H%U!NF-z57Cxtf-hzW!-%@qYrHu3rKTu2vEv!SoHP`94+;|pf%Ww(?!tNgBnsMp zabulqkf=lndGy)G4W1w!zgQ*ew+(AYb=*a1I!%8=WK6CAy@r_F0T^n2UsI}c(z)mz z5MC27K@gYw&@K`&wF8?Z1h=cGfroWv_|4_*xO|%*seK_b1f0l8krLH`ib(Wh?-;vw7rA*OR$k=S7k6lFRv;~*@)Vt~j!L`Q z%yETzZ)OaC>BGu#dJH^<6^T;pO~Q4>dxFE?3QcNSAD1^^;%*^@lq%s|Xz-5!WCj#$$2kq(Z&F|&cI)QH_ z!RN)vUCDOQq|Y5&)dnooQ9aSG3JZ4o<=)UJ0Tq#{N;Ws{x+$<#8qjs$Fa%D^q%svK z-raH*aw9JN@m~w*jR>y1Po|q&w!aFEV**>YO-k8CA7}t!yydN)y9&Ld-40~S+>b~u z$)r)YnU`|C(@&?0d@9_}8a4t@zTsHj`&>@x&N`g|6$1+gv$w>E?HE1}9>?gJTu5YPnyW>VK?whvS zU(OYHn>N*LorGJUYijP>*Zw>{dQlG;rWA1NHeDf*^ES^y5skl#NS47T3SXsRdf z?DX|3Y^*HRyYrukx7zy)$cwT5h)anCa7DcAxuBa1k;|3}DRjN>ef7@hla7yp4Mz^V z?6@!G%Vr%hbn(A^oY6E&o3yBP{vm|xp%=gv(q2!Df91!r)6za_ML>q9Q*!WXF zDX%R`sHJ>h<09ps&WeZbCSyiNnCA#X>iI_=ae~9$JDq(vn6#P~@BxR*p~p4tH5b4t zp6OE#Kercdjgl)hAU)ap1WW9JI>wqmqtywNs7ur$tKGxmqzo^ByBo@zp&HlbYDfV7 zXjv^7qq8Zr0T}$72U7!B75f{A&!J@0!_Ke!+R27@Jq#pz@pwxFi+3rfi!s%wJo5kWqzz+ld*1qz9UN9`#Ri(& z@Ab-7#qVoar&w(oQImw(1=Rc~UK_cfc!SMeLEEjNcFw$lOMN9SXTRJ?-5O^_N0Ld5 zEd;{dS=7%C*ckU|QodJAH$EI&S)3^=H-3O@R;10YHO%_l51`ODyvsRE*AOM~E zhb`_O>g|YoVrpVg?pAvdpfsQoh3;|L94g@5QhKW=iBTEXx=2h$2IBwed^GPZRKSI) z*@%A}4G$-ugw~OS9ndi_CbX?Eg0$zOsJU7`Q%Y?- zCX?;L=x99>fplp;zF3oIGO^m-!7EC1S(emk&S+Df~*wMyMZ|_ zsZ@(+i9kdx>~yTst(!<7PApd=sRRkGZz7`k&nvn|B(XGr&+RcOoX?pC&O3U**9@e9 z7k(ts7IreLg{n-h&xJW%MHu{zct7@|G4C8~BP^k2D z(Akcnbj>H20TeMkdIA7I2Ws>&;6ixssS5VA=rZgi+w4mhJh|YH@sIEk(dForGmpNI z?PQl3aU;pUcK5az7FD-U6Jk)DoGvNf>aXkreT+c;d$w(x*FY$`s@I*jp+|VkMqyMu zG+D0wz(D{qA{`|#Sy#7ICGBYSBmE$C#ndnZzAbe3O3K|Wh@t`d?Oy`1VVy3~VNkp} z=R&P(9=49SDH5o~1b6Ci_eg(VOQb6so^P$A;;KOhz@LLC?ju6|_?lecE6OLx0|jJc zneTR1*9uf+<%!=#4<97@1##FT@4D`^nJR-9(U-vIN#MV14cOgxS)2YNH~OX@{(nw1h$@_58o1hpWmeB%n$@=8W=134wmu!eq%m5>zg*OeM7 zfK*8b@QarZ{?-NqzHSF9*GhmY>@V4ZTp7SMYHC!KN$boX`QHhDcHZ0qrSe&aksRT4 zX^dkW(B@>n&n!czCvqiK6{}VAdz0anX@zwwG@*A=ux_fCqCJe_8Ra)tWL7w%L7Hdu z@@SDOK$5H(9HLK(85_k5J@KW7QEV#zFq5m6xt5702+Ib8fjh!DbAHp6fDXP!E?i`% zDAO;3MyQ)8TTF0^JyJ7=0c0jAN1+R_`uAs6oR~s6iEnBAjGeir_;a@Q;(glhBSW4I z(Z7F|)j3j>A8rBZShUKWz|Um>u!ibUUmQ(OkZCH}=T7iTd=AcVv$P(N_p$&66AsH` z>V2`f%LHlLwQ?i(wo%B7UMux2{<`Ce)%EKcEDvWp4mYTUS~oj;znXj^XZoZCHTK&I zg|OMDUh{O!#+!dzKUd`q{YARW);h3VXmo8LcJGzf8CE;a!6%=I|6!H+IzjFNdiTO1 z(9c0PnSuVMbuJVUASToG&I&K3U^dH?X7nu~Ur;$mhwoEMzbnSm z|3HxwrPr(Jv8gI$TMDdY_Kc)j&@F;3 zdQ|cce>PT%-swxv%YMGc;7%Ue=Aj|iE$XaQpmsk|09r^f-{@>dQ%Aq8+s|mA%bGJd zIbY)DO(~%K)5j7KK^Q^Nifyf!6VR4Kf4&?<%O(nwI=kdrlc@~N&9dZ z(m=;XKpmWZkdN^KP=sNUi-^c*cvKOVl(1k?9*GG(d0UO=iT(3KX)*@OPd@>I9AhW>wrTXfdOU!zvd5=7rJhNLln(IjIf;t^w|P%$xd?35|kk`QM(4YR`G z{J(X7Tqjt@tTp>Y#$enB5%qb%1IzKb(S|Msp!H2sE-#icvbCG;3`^4YniqcUveaT& zL=;5k>(5sMl4~!tOV)oZoN}F0@Ghl8Ehju~gh#`%gRjeCm}?6rIiOjBRAmV2o8soW zzlW}B6s&)@-_>~5S|+>yk#Eg^myjm_8$`z}(LrNT;Pa@rI1&^0wTA493wbDe5>hhw zs3!bECju*<9reF2e<^pkHt>%B5E6Zg{P?vi5rVQdnE_t_0rY_6BpJRDyrm{v@@1HL ziv4E0<~WGw_Va1v52)v@eb>ST;G^d{@wcV1(!%lpnw!_*gznV24*AlQg}v@DYj1OW zS@Y)dLzpiHb2{_0Uadm{K=&=a8^pHNY=|Fg!|69E)!&@x(-aqHONi6xBXqz|6`&gXzC=Vjm_yHv*iRJQR ztrd*i(mtjM?$3vpxx3V<&acap0gc}V?=N=lYQXzIUl7E*roj)4$f$+!kgN)3{mzCV zlw^|z%$y{o{{1?#pUbSFoI0>Y`2HlTpt!{E(vFssFUZZSpid52Z5EYTD9eTIYoZk zy5=Z*pn!`2I~QY1saqXhZ-*}f7``3vj}r$1`q=_sd@$@p5e;mQY*V@+1_aC$2deTu zkLT}WTea;{)iDdkr@Z$3P%WS~frLp0V^wvL)ecTF{m;TFh!2OGGwCR95` zL2%T<2Ew|`z8#Kx`L^pI&8bU9z|tA(lfHKoYg3=Yj%RuYDTt#F;T7wDXU(ycA`_aC z@&g30)F`F0o~ty9VLDbD##H5!Pa;b+8pV|3naEbO*Y|}}rq0=ke8rJzu*oXYwF>q< zjRyUoU9OhX)*0l}qeJK}!b%7|(}A_-L8trPyQuhr{8cB!XJThi`2c zu;=Fi!6#0PYdWI_LR@73%Z>YzaRw)Yfw%Wf8^_YmWa;&9ZPzcgZyt!A4{reLEZDEl z+m{0j->)s`TdT`tj6KLpeU-EG(qyoN0kute42(1-48KN`xiuo$YO^^70Gt z3q5t6ZK{pQBEPyz-luxrhYdQKw8*KUN2FfYI-_A{ zppa0j*6{~ci_plaQ6EkT8MMpJlXQw4F8uNMi^=0sTTc{$^B;mDp^X=Pm9(_W4gYw% zCW>VkwIzX|Jl+pX(%jcGxnq)p8gk(}%vwaoo^r8}mPU&stKbk@TV{a}?8K?EuZtt! zSVxLscnQ*ba03^Li)99h)V2-k0htnzn)^B0c&W2V`BJo);uR#{1!&qZBG{UO6jO{? zD+dPonpQ63j*ry&EJ#7ym;>W!a`Pr|w3SCkplsJ?-5K8W%L44eG#S{QTj6K~ZK!r| zbcXYKx0%$&!>E2{MYPL z9lJin977%8@4My{R=6#C#XL3WCm!eH1dtV0PO_sdU6+aR05PEivzD+3s7sn-cYH)p z6dX?!kY_FoM<)x2H&!_u@YSXnVTIeattCN!z5&gPGXm!97Ko)XFdulO9MoTQXzt?Fu_~D zLgi+TfxiMD+P=Q6T>me09|1!4B<(xiZ~Zs%p7Vdjdz_(v;=R9;e?ooXfqskblC$6) zF#wG!xzOx(L{o{xVef#xMt4*_CnJ=Y4jPh55iEG-bwo@bx!GpGnU_*pD$Ck zY!l(J?d50B!#CgQ{!n&wCGRTM4jnqN2Qhj)oUs-nhsOcI+h{um`f?|aO)%I5#t*|( zDFKFL&au|{N{*ps4UYtJ8^3jP_?{x*3=f>p>e7%KpLWQqKqxl*27r_Dacht*dOHTBbR+0!6$Kb)wvwl&x}(@H z(wS%$q&y14kNmnEus<*e95LiuYRg8`fy<{;(UyJ&k5o+GRlHFOFQ;(q7iS@5N-K`q zJ=u&vgxt6G*UsjrtB9X95mjBc`&qoprAq#EfQsRSg&2VF^Ke2#r;p)wj~URz8Q)x$_TP(m8EhX{u|;Y z6z{Qph!=FOS{v;N8nOzWB;h|H8C3J+8ExxnZBno~iPUz&){SGo3*P3PX~XmO zyC`wSv8loY%z}}qP&jTaaCsa*_u$f_(i2LF`z0o*b8@-SYik|hovaBSk zO)w_=M4iM9!??8C1?aPfn->_?dNw2LNM5F0Yv67@)KuV%U(A-M`ha-MhXtHMboV0X zL`(D)jFBQ8o13+yaf|JVr<12R415BSjUC>M#cgcG9Hp*25MudkyBV*UL=tB8Qsmvw zMdq3{>T3QWLU^`~iJWE0g2~#0u*I*Jly>}F6>AQWW@?+5{dt%fUkEd$d=3q%({nk2jQRo0f0<=+gSQ@}LA z_IY=(H+Q7q^S*Pl!eNl}@j&pO438k%KLTxSKubA{_hjif8unufR!KT5)zp4a5+uAS zy|BhC#y$d5nh!#v9+Fd(Gi!f3>yFIcCFHV?ytF(yB4}@mH~|Yq7QBDuo>;H}pJ`c@ zu-4B>vVl^V9im1<`Sc7~RHizAmEA}LUgG0{(6u4}nRC99Tv%ZgQtMC*OXX~e0_gN)xeRfl)R~4ZT|82-+M3iE>~s)3 zKy21;Z~B}x8B9+xx0gyff@q8kYm{D5(cV&1NM#sElL+bh$PrmtPcaxQ20$r!%)1`? zL?&*KF`SN^>h_qLdNkE3;Qa{ZwZ3B4Wp?2Q0>Cwi!{us`fKMIYpx-Mb9EJW<OmD42mI0Xt zAo}x3ZJ?)HW?DhH#I=*FPS1~l-&(dEW$VboEwD8+#^tl+Gw9zjzP1_tKQUe=>v^ky zPQO*QK{cJ<^L??=y-8)N;;$+Z=uia)Sonu0leCpSpj5!4L?LPtDG&*5Co#eNwzM0YKkKQ2Y$NMvZ4*}c@W+Q!GL3-q)p*=mB zAG^H1Hy0}e`g*l$<#o2HO`}a{|5Le3A{SRO^*hJ+Vd{xynDD_{?C z`oPWCA#y*Kx!{nB6(hB4N8pj`%FTZX1*WQDxJx%VCELs=ALXbQceeQlOwz*y+1PE* z79N;mGY;gelIx?T);#7FNUGD5AH^qB9eq$eF z-;@;?av*0JizyDJw8wuw)*E2s+^*b3eg(KYiEo{=A&KMNm<&1!Q_;7A-441@RqI%1;OnA9T<{17 z>8-Y>GCKZ#I*oy`S(s^Wvg783D+3()``3}wzNnuHRtN#CcSNvT z7lR|J)B(Ru2mKS1)|w#p2*-dvFo%3O$eMp?<;p;l_SSG<3n6T2oqrp6QQl_@RIILb zy4JTjFy0{v-h<}jyzt<(rd;sg80_DuB7B!-5HHgqPKI1qbrrkxdn_p#B0`GXFyVGw z+y7!3*N~1Vic>}86{}e>qrluOgKZUPB`3km`-c>wvo#c!N6?q$3o~#Ftqd>vGpj(- zhx#lK=dH`kJLu|3YO-~~CRL4f*YDo8!s^;Dv9i|A3saR29w*l^e#YH$th(MrDCDTz z0K5p&xU9Hss0uT_I!hbVK`q#g^ue)KlH;ClRF#RRe2^4=m%q$iDI-JcANA?2Rz)w9Ab49f+ zRo{pRuO3uxeYp$<8LuHoAiQ7J8(b+jo-+k%r!1*+BNZ@0npqS}N zw&_ro&*^kRh4Cl1fNU(E-Q!J9j~635#UL+74MZi2TV=<3cRDWT($Zo#ue&Yq4XB(_ zLtwa(+}zLeAzRaW7M2phr&R}v5RNIX%V7#7H;70;H8`>KO*flOU*O5)(Be<|GH>4B zSfF=|d`=TBC;S|9u>=o;gX39mzA6?Eef2r=4|e9)^WkT-<|p$lY;2yJ(Qq2KC-XIC zYws#sUMF+{d_JlyHarX5vTlD*)VN)w_Eo7;T*wTRk`s#0$}{BkaEmi1?)|T?QEqnH z^UEUCsig5g=dnFZzD^ull&KG8iXtkLojZtsz0TK*o5b>0?o%HG6#x13x+NRgJDN1) za&qrfq)b(tB*l#5=9iuOaZbgB#}EW(VXfpC98qk=Z4nV#_bYfvql9G5G;zQ**2a3U zuq=q-t^N9-lBw)&`*J{<-%;SlpOY5J7RR8y?l ztx6p-RYi5qpwl(vL&-NY4Pwe`k63p#TRigb`&^y6xF!|OHh1+M1H#<);r9P%?<~CP z$eMnQy9IZL;O?$Lg9Ue&;O+_T?(PyKxVyUscXxM(douIRH#7P2-hbfUX05Xt7W?VF zyQ}-`uKHDNy`+H$wemF!mPqUs^{1Sf@nd|d1-IteQj;2?{HjzXFyiSF2MZgvX>K`% z;tI8Wl-6X+$`i_O-(RjVdO$1XRWoS|x46bw@0a&^qmG#kDP1rd{f`CKMNb{^#?MKQ z$41S|%^FBHLxXATLhv86Kdc=<3W0EcX5(6MdViJ0=n6A7krElq|E0n`X*_}Z#UgtO zV|&`!7z7jz4x~~SKWeHFrx0?Z*CEIYs?mb8Ffa(8Gh!ActkcIgO5)?GX6 zIZfO9pd(N5y#FDm06Y~poSXFoi>4b}4oge@YW%Rccn4x@a17EdI}7SZ8D}+)^FeH4 zrb2S3RR~y{A~RH2QOedBZX!g5CY6$ZhY;l0r!U9YyFnrDyIy`A$PPg^gjtU17~4~Z zuPu9xq2Bd2A3sa;tZQQ5`j|Z}r}#byiX7fF&+B#!kuw`7ZC?UUphC?_xCA0uHjS)+ zED>JYZZ0~ZYRJsFJx(V}npNGqPFrPKi=>rSf7ZyQWc)y>M^sa)#h0y8uSxDs**c0Y zyPxh#K2I~4uE;6cDp0>5S|05>!J_Bhi0IcEXF8h}T9+X;o`$9CJ$8b*GsnE>#;J9c z2s_bT0r6_S-H^bU$YgL$KsRU4oqER`IYHvi~W1Z2iId@qhGpE}yg z<(F_zOw2_gp9$&6aMIe$Ak2v=oVZO{;_M5E`KdMqxD z%#?vyd}H5~u{zJvs%g}Zs0R(+*DV4U_;Gg>x-896#y2xYd5C&PNNo;Aj^4}0&nS*v z6Ji`sh1PfH{l*05Bitv5?_YbEsmf*v@pe?6c^p8QvxCJ@F2Nd=$Q9KL4%Jpa4ktx* z(O}E9Jw3H+zg-{>w@R@op4BXxMX}I{YoWM{Bv?s32%I1f#&&ieq|RS0{O!M4MgQJE3EG+e9ehiNu@3?c9fNj7C--iq5aM@I`YTFktO> zTF$$EBHu=2QUYFqZv{bpON7&kLPm`>DeC7sw6$aEX=xlH2`5w;=w*8;8BVo7NQ<#pON3;%MEX=b%w1 zm$`xc`3Np?%5+|Zdk^zBjpPaF~=;*n{q7xv$^!RJpB0_==qb}I^rUmy>%ilYEMGsK9a)R`K52ZzIzJ4_QYqP zX$u4qtr=_8UYuqg9g!d zdhTQbo@f;UIsPSl5;Wh*)QQi_=y>*et}9`mIbvX0rxRj*I=Iy4AuuE>3~{OFJ*IK{ zMZnkN=Xp@PvoZ);pemeim8v*7a82QpLnAMtx!h%IBFtx(=v>jxWkz~2ymjf%RKe`5 z86XICf#&@Pkh;dQAd|R<8SOsH-|Kloc%3KM>I?xLN*QcpS6{$Dm`rU{?jYB|{6I+1 z3eiG!@#=`Ty=#_Q|M+2j+Lpf%Q(gdM8gxeiF0aTqI{{q?fpV5>ti=sJhD&|E4l5mT z*s}p{AgVtSf_bgoC(ii!O|2L7V=d^dYKSPTvR z31x}RT@dWfF^pijA;rf^IyORL+gd)Mj*ic(ZaGPCW6~hVRVV#is2bL8Y&^jX+d`_7 zeGSdzs>9y5T}6y|i$DqQB%sGkv;wmac-UVUf=H+ih@&(tRzO7UO02q+brFc|td*{S z6PpcFhBq;9jjHEPGX+r!-0kAL>!=LBUOTflTXj<{czUYLSNV+wo5Rrx1mJv97?t{* zVd)Mk<&_EJ_HaPk@p9u-7#PDG(Z$@;GS#8#(^gFexMZY zT&1?A*u(;%-BZGosRX?*DFsQK8`T}LCF7-xeV!w(C^VMJv?~u>>$vJ^xJ+D}{g9b7 z)^oj_>X7GS%4vA@uz{W|GMw##7JA)vvpVle(^+>DOSBm%ei+A!g5Oe z&{AAtQ~;}bGg0Da`V8o2Sd z-HdILLo@IU`AE_W(iTz-UJG4yxofT>%dBDW%7x7>D=3P4L|tx zk@5%NVO?dHz)R++)XBElBQdvBgQd_D(+FhfKD)##c@)Z=O~m;agy`xhc%rN9qezH| z%fzV08-^1#_YQS`YR^BsHOlE}IaRi042{8#wjg)8Ni9Kb4*TJh(vy)w{Q}KIfbWH9 z%IhBq?i1-gPW8P993kNu4?}HI1}ksxJ;sa`?^LO_k@#i2DCCGwmlTg_orRQLPr6|H z^Hsr%)VWHt&pUmrWy@fU12iA7B%OJb=RtSv1)^@KL8{y1`4=?5yeQHlQv(WaW(-=4 z@$gLOWq7z?@8Yu(&HY6pW{|De>N8NLOSwcvIJh^53rE24vaQ(1I$9ctwA^k+1jdgGEs}BQuk!O!ROPKVP$-ZEIb&w6_j&P50UACjc;;3(Si=>- zSOhfB8lm_Y`|{G(Qd#okHhR9gW%3y-Y&9I|a|<$i7~ zWA7_&F2phXg@^bxIlx*I`y(wNAb;GWL2$0O21#x=FbfEN=p+sxv`<*OUpKq1;84Zt zm$@W%AQmFmH*+iW3UE+A1Dlw?U*QFLw@g6zZcT!}HsIPwk|2lt28VM66I1M40LqWC zdGcqCukR!AW8bZ2beC^W)?b%c=zpMTbZ!`GFgyg9{LJ=>?ijOirb zF>DL_N@beqpUc55Qny*UAW3$$Wim+v)UcxVNn|u$^0WN-k-vvF6#MN9<2` zYKFY#GdL=Ykk_{}$Dm}8Izs12+8BXr&%Rp7j|MW=W@=DPC5WNt!dCSbtrd^H{%%R{ z!ogkkOw7(iPJ_S*z`5f=V!+1imJ5)7dSVMUhUz0mPRnS`X-bXMuz9v7261eNxzWcM4`#e+K zy51_Y`bq^AWE(Oah4Vf5Me_;%8{k#?f5*&ZHnGDc05LPc|63B(A1hTK|C&VAE?OXu z9>Qmln{X@{LXr-mj<2ySmnR@Ev;65!&LWgJlva)=Bx{tiSNo?VE)kyX;in`H!;@J! zgc(_s)2hV`?LISB8Yx}kpbcvVB=zZr#Q}n2Z z+g%}l<5Wc-@FjHy4k0_HiEb)4oe`uULz5Oo*b^vAO&>rJ_q00C4d>U!PU8|7=tO`P zVF{!iB`QG&N4qo%P{h47uB<{e0^Lnq1u8S3^Sn`j$=^K25@mrC=4hWs8-NR(y68ss zfi0d~3>@YvIBn-LUPj8_o~GY+U}xLje>E;qANsr?y=Mqk!scPkG-O<7iBao|0-1sO zham2v9>EP+x_zbflVC)wSwdBF-O{M>t)!Y75?S@PZ&jtq1>aJEni0It5;bNtPw}~Y z97|a5vQp^>{*c6x0FidGzz@p7eM~gcy%;&gUtLLEdFkMTf-r2RND81bk14`Q`IZF3 zC*Vi0rB%pc)4(3>$pSTSdqei*?(j8osr}@pa1R4~CXS5bISwWONNATo{Bmid)jr}$W?HX>!E+(sRVzJ8w z>Q^*eZdOkPI*hSM_(KgD>k0{6ZHFI>JfL1}X>tBo1Za*}!Pxtvju@j6k@e1$de&aq z<~;2bq4rah;ZNBca*r`nbvi5Rhy6cfZ`vB`TD^9Uh-^h{)ky5o%!e){&9d4j3tNHB z->qc#5d$)x;aIe{zLmS=qI^9xDOh7_{KDr;B2e&7G)TJlN-RT`r!i_UuCqHPd`o)2 z2N5hGq(H^#nB*?w&hTgEl!n;8?ix(InlZZ-2a4Yd-$Gw2aP=|JQ0{~fY1e$ux8)V{+6tDow(yFy~g+N3&-cBN4 z#%p&>SaB>^6T;<@r38F-4qcIPx+4pWtYMd>#0WX?{OqeK7voOzVn(e5OmOk z7nHaP{_bW~7;o;ZeqxuKU~Zk@Y(5Vuy86Dot|~@nsRogFudWZa7(;L?Lc3Da0(oOF z>B=VoUW^5>tT2YGtPbDP##5n*&R5&p#C8K@*bakxc0>O6flpEPy+U3V){zCVVNkcF zQ29NLun;C;q;bZf5?3j+Nben^MGS020Eto}-}g9snAqU~iBh~)Uf7Gl;vBE}-V0n_ z4W9`B0+x?C3CyD`0yA`s{UU_A$v^X@?6z?chL7|b)WE%)r}_GXRE7f8)WW_VXafY?gM&TBc;*!L1V_LfycA5sDA8 zUo|TXV4j*L3igvbLT2cygCclt#MQ__q(mv_gD4W4J>vyv*CZzdPW|pn0a;UgUoTb; zLQU5509jM;CCjK#Th&D0OZV91CWHdx_&;%vm;aG9#R15gn*QpC01&PLvZj6t*ZMZt z)kipH(5n!fH1`ZwSF9Qv=puaB_Vk0;{FJC70%?ky>^DF940SjmS2&iEY*N~y8nLgW zf_d-FW`7_DM72%eFDM!gRAu!sgEgj}93ZyxUG*Vb(bHFNRUOxX7Y2t96Hlj@2d8HW^_d5kn-IpD6qBrLe@S+*A*~A`_4p# z!HlTGySPApiQ0Nk7fTA7o=o#&|GrdI{EMmG*5+<0xD9=I7sxbeWBTjuQhnxIuu*68 zkfjWT%KJLIYRP5=5n9Pjbw8L_L&a=T+s!wxI+q=$8Dyi!&4YZ)i!aRy8frxXFyR`6 zP)t{d`f=EER83>Z)3K!Y-ACdqfJ!iaj?ID2z{d;w(}En<~q zGKuhbbxHSElSU?w%PQ1)x#+j48TNC%07@nwi|lX4mH-62Zblc*)-)@X0JBL~HNoOP ztN5;r+V*!TswVw-#8EV5mvv1I9bwe3HO2=XkU=Ft z&wi~+ONe`zrEStU8=7Vs8DOgrA#P=GrgdiCB~b;5McrX8o2r>2sF9KlkbcNc9Gd6zy6+z ze>ynAuDaf69v+hs+bM!}kI~*!FyW2m>m0^~pHC?mtBPm*pD!kC z(Mu3JIkulIGq6b&&A( zqdg)l!3vkZfum93JX-)L}_OSn+v~N4rW}vAo)yBo!U3?121qDHB zA+N##1%WrQ`PKoxJ39>>A^Z*#L9~;BMS^Z9pg_FIf+9FSWhBnW<%7>zf2rgUIF;Zh z1;>x9ib|A{#owgqk*fR)Mo@i*vvumlDV+CUILjDFjdnJ<h0mb)Bv_DMeSeWy?cu}#-VQv|%@&$_-Wi@zxqD)CdK zMviWJUk}fYwr(-S*$SfgLkM3a|4tcLn{WHO4&inu;vGvbU=`Kms|QHYgxwC2WW9m>S2)cFPWk zVZ&d9^P<0?65F-~C^rT+BaJYo)3yb~)mxZEMAz zkmMSy`*DJD7bfJ!LlhrAgKH56+p~&RC{YP~5@3pT^=VxwUTF60T-ckRTA|45A#F}o zEON-?<6nEQ9OL_P!+Q!WS{drgM-NRrp54(Y#jbky@MP$?xYHQ9$N%O~uwd(xLxg~g zO3Db?@6#}D9YgA&Q{F!Y@!&*rUxu=QS&rP<`30|Bxy<(vk&dC9U8G3<&XRq7Vc~AF z(+oEU=)TNmdkIil$~3(SQ*Un-va&C951`m@|lUQV{UNXAyya5)9_KrJZ=>~wi_#tTo+>f+sK;>ud0bId1TJ6?AcY% zmsvZD=1zz7tKSEw2hd0%k89nye%v|&-;@>IG_I$C zi-V_jYFX51o2k+tqBjyYq{vEZpF@$59Y#IF-b4NFR=+c8#Unwc90<(26nK&1$Fb=N z#2GeglQiGAiqG0}&~|gFenS}GMJuP`=k)Au@C?(>v%CEkq1roN*2MP{s0YN{xr zt!b)g=DtwstViZu_sXzoh4Ty9~8kfxK z7r$GTEEE(o?%c^D_|yg_iMj?DjKe1*_P*>WN`6@osCv#o-8^cdk)tMPk#IO~oPS zA-q@x2Dos`)$ao45W|!0MG*CAwo+GBaxe;M5w(PV?t&Fd zk8s&@u6V@$K^EFNjqPeMM!F@&RTn_tVh8Di)`&=N#h+&Hf9@e`%t$1vwV&wNan1b zU9D*NpvU^YUP);j*QB^=1#)@1OOI9j?hHyUabq%Tw3M5`X10h@{V=5Cak3x zsq@Rg5TjZd=o+5AlVrW;j~#^MjMtZ^JA$vTH(O5x+3OO`2Hc9D64q`tpnCdN8O3Q6zj9vPZUa92{HL@QOg#4+m0A zi(hA@_$r!!$GI6k7wCsmCsHs@9PVFGS$f7ToZ6tlx%$&KBWQjOBQ;#P$a<-7O1ZT{ z-LOF)IbmhO!%^3yBZzpgH579;{Bp$*Jl)-~kfWNcZH5Me#VL4D0>)A$T{3v1t3C)r zS(Fg=Z3rT4rD)OiaBlwv`#ZhGUPPFa=xC9kA@x*Zkp|&-0#jAup_;CC2m=msVD-U> z3!4rdM7It-yr<%@V=jh?RA+&LQpW;=Pn%3UrJ)tA@NIs>w@U1uU_6eUn-DWQ#?+6L zDInbiW|RRkUz`lZD^ZXGfOpq(fZ3z#kG8udY-f4UUu~cpjqB4C1oFD3 z)rP)h%svTiWG+RwMjYFKYD(OwV0dbeNXYr_%!h9})XG|;2S9oOsot3TG;NVu{N4~arBH# zPCe|M^?Qb=^leHdgj{WpJG)naALloY9CG7r?=C<&Es_tTIyTrnOV>oSsEXwX_+cYpnF*_S8RaVwK15OVI=)V(Ra^1 zeA*X3Mg`G_^p528y6Ku@sD&a)nyFzO9K!abBgpwBk?vfDcJ^-2R96vSeD|_c@o@>oXBoXFA+6 zdjybg+Z?oG{I8oF?I3Gi)fs!{`0?cY_GxX({SW+DOG*XNGH-j#CTsc1ds2JjV@Ts_ zm#^y{N1C=)oL`;WY+se>QaA3t`oj7-X}wC$p1E?RztN%Ek;~F~&~#i~UE!-w9&gB7 z;s(_FPm|0jzHWXiJajh;YA=TpN<>lq#TAYsGFJ|G-JQ+t1?X_Ujq1tu5iXPwH+Y6P> zFDO$jJ6&$f?Vmx+S13{)N|ZF{HrNkFY-M3}^e>~+X)ARkOA*vl7sWO`gwaapaYfcb zGd8xfB1#gwuh&F3!JyoU;(>x`I^ zb?z72>~C1jT2#XY9-Hlv<*bac#q*NFDdxqNt@ zo<`(=Zh-F|LO{QQ0SjM}i?MaQ-j}xkF462FWt>)+UfxzC&^lSDE-Wc2;VFZ=dY@&6 zB&q_5h|lBs=pZC24>#7eY@t57!4;G>Mx)H_bS!|LAcM?CpE$U)tXam*&YVk=MOx{* zACeu@QYraKihw&b$bN53&rN@7t3Pt|u^MfChVix5cB}99_O`QA@RNv+4ngK6+l6cf zkD$uk*;>2vnRZO}%|wptanb$WDi&uBm!;}G-mmfWUx|+ za(HBSb8>JHxnj3J0NK@ziRiHX-d+~xuK=%jOS!gIo}y{i#-gUIRV~U? zW@r?E8=sw5x$!(bpR|V^H>};{5NuoJerL5{!C0t4ID$Lfgj}a)L>gZ^Vq864CLX9L zH1K#75^VvW)FEr^S5&fngofaIuaeE&5<|qCE_ytfD|UaOp8RU`u?n-y5nrVMA_1ge z27_K(BH4s=*$Z@ML z-0^5uZ&4&6gujYqMuju#|r(wV*6X&Dc+f8cKr(Zj{sg)&fRL&vyRIZUqFP zO|ndCy}Ki@pxNmpWub5vw}p?9 zk;%?e*D$Lj*W6H7S06-#b8;KC$?f(S%Z?sEPMX3(AVO2 zQ%pb*n!WhS#MJeC&j8n?zpD(f+eN>1I22C}yN0%(SW4Zp9D>dF06#TzwKop>L{Uor zW20My=Bxq6TxuRS&qGzXOEteEFxd2Ps9c(P_eTP_m#OpB?kG7qQP|}R*@X~Bt@B=a zp>Be+=IH3CTAvKxLOS=CXBS;%7Gy1ObSU%Job$;hx3^c%EK^tsMp~BA2lU_rpnHiR zZRiaW@fr?TsMKlYN{7tJrmpC2=IhAMD8g9FY_xcVjL^^*>EsvVA~`B2p&>Nw^u>c8 zb+H_Kr39CKbB8NK3m+4K60PB(ckUS)HJEgd*xcCMBNq z3uu`kTSNNMBC&BTz*4S>SBmF(Z^z$BOylPrCl6Q>B#pk2I`ra$BP5F;0dbV+Ucbj| zTEbRAADoz&*f&LmZbHtKoxjA#!iuH^r?-($e&tQ>(5ndBf{9dA&t7Z4iFrl!(r?;@ z1ER*rt^4}+1$JkUA|c zdJpDW1LOJ!J!eT#HQ#l>6&x?oPl%LBwo{j zH0YMAm4h|Al;Rb2mBbVsAtqFkIZvd1HH)OuAi|q>kC^2B5qP=YTpJAbA;7}L(Oqhi zf<9UEk58Tu{Nz#4C;C8O#-fBo-V8ZjhK%ChAZ)gdV01`tEpo86HZG0u#`?~m;>HWV zgs81*8YJYJNU4M|I+DfHKAgf~$n!h%nS9kgnJ($^PxEo)>1pusGv~qzq%P$wJAF34 zqz*xc(fpj>B8d*2PE5Q$?D%nB<_l|4Sql||$*LPGcM1YoozM64xV!s%VOU|P4+#=U zU;!df{;4eld>*DlAPLpbm_NYAN{y@zkz`Nz_GJfIRgh(nXpjqB-Q5F4^~*XoM-M@O z%x6pWEX&X3O;AXWWZrcq;u46LwG>r9K!>52_Z>)}ieiZq)~M>)+Ms?UMT^2jYWy-* zqEfy)-y0d(q5HWJ6j#0@6MQhostzi!+4)RiuTVDg5lcC8LlI;bgH995kj%4(n{5(2 z1yq>5jt3l5Dy3)5*W2B5wqdhE!U{tyG#749L|s`3D28<89W4qjp})M8ATjdy{Eo-# zH6?Rt?g2Kz_S`ajJqQNKmzNiPgy}xP%7II(RpRcewDi>6v?{q{jJWAh7$g2|AOAZQ zp?z-%D1Xj`%9nB-jhyi4(uSqF7twZ=Ms}< zZhVyo3&=-%I#e?S)DlqvI5s&-FD15Ve`>K-yLko!U$7JK9R+rjP_7D`deh z+?d048Q?K2+2l8ZNMfwB5x|`-&as-{H{xa6k@I54TMk>z-aWAiO*lBh@tBzXnb3h#^4n!-xgPFt|aG(G=nc16J(>t448CpBr z|8$yIC=5rWGN7)g9P(FO6(`-1fP6SHj8i@&rplFRzU}}o^$E9lpZxHoO*m2W34P!$ z?TM>@>{L5omCN^sW=L8?oiGhjd}*Vpy&cnNpr5L9@00Ta3Px><=~3Gr;Rs6k$H0f8 zKycV=ESII^G*Uegnqw*l87_l9y!@s^UEM`|m;Ahh@Jeb!Ff7|vj=)u`?Cf9 zK>8Tlm8B^+JWpcotvdB}b)P#>O0Dus$T5cv^4F&z*66!$7}Jqv%-kWL=I#vEu7q&k z0$(_*1u+|8R+rT_2ndFZy8FbJ-_Ha8b))O*;3k!eq=n6*|6Hva$~-IB&9A z9P0%eLpZ{GD}d#cq#H@Nf*415ftF-|SeX+|nQY%IMYUL-r;zr+tZ(Vv4GY8o)pr|i zI`<{pfJpho7g7iLG1TIX3bSoMV%Jx9oOe2w{c^^mwo?U{;;dEJM7ih$iWq& z*KMNL`nRt?(JC0k@_@2Ka)7c!NI+1)|MU8zXJhlz4hVC=fGM(o0H*T)_Lipj(RxY% zsg>k{fF^T2isJ(r)np%9o)E9xyCSpG&{i4c`R3VEWY%Rn3P}?2P{r(GkRE4FLO#V> zp%9p_1%Mi;om^J9kO`9OQzI=GOUZ@Fz*0DEg^oyDNioG%=u%AqK_Bs?)s;M3ZJR5; znQIDc3Pd6+&NK%dNzLv^WsRA7C3OUu$M~EVuc8xw!-S|`8VGEm&?A1A$V32hP?aF4 zg|TFsyol%_;%EC^kqXCDm~fM@5XsQbZAkSX=#9+rTl#c=YPc04Y@Gn;gEu62l@}wk zHH3GdC57S9EL9!W&NP}jiWIF^G-PKAJg;JGSOP3>gcl>M7aAB!?I9Agm3PE9hbUT# zDUL4`H|i6$?oqjU5yh+CaKglfyb|h%(iZgVK58cAkzPd6)2T@hc`e}>H1;us;jk#5 z%BIe8O6gDavaSgPi1ojGyAy@(&Gj`sDny2XB#@QOpw6BmpzjkK?;7pCx5<-^ znrNsm@ypqGvU#$+e=y>CE|wO5qfKF--fw=tA@c_E&6JL6($@OTn!j&tT1(_5{rn&! zhW41BYiTW<-%~Ef)ib1EdD~-l+3T4Nxg@FsUEj`*spP{8P)r$|(JY?y>D5h^U}Efd z-nFI&LRE9&09;p@f_oYu+r9|n2mdwVM*?>I%G|Jvgps2*GWPI^q8Vsq+ zRLwv$ILzu#rZ0e-?SIQjK0|)Pv;*8^R)FU*%0F*I14nxYYs>$CC;t8PDUH=K?_$6N z6tR9nB)h9Md#p{U%c=9J7@X&#cOt3%$T~qvCb438+)jUpiq*W>GW^u(I_AxOah_h+ zhYl;jA?3yE)zMM9$*Ok*)`I%!3IS6gzLZX5%m&0s)kn__P=EqvRWBPVAs|7Q2^c58 zX`srmwzDPdj<~Nm8Qc}m6)>g)*Kdz#;byD z?k-N1n(1rY(j3_Bbj7P|bi@||Yv)$W#GXnL+Fp%3Um5L=(~RRcu|0tiVVkIwCP4#g z=gZ(MmCi5S7`5rDiI~*_D!HRA2^yN*42I@k#@hi~0kn7%0wY0&2Kmn+mPnqxu8KJO zhH24V3KwJkGQ|Gb8`{P03qYB$wnN+kMP!m~kh@=qtKR1+qx`TIP6bl8HO&SMjmD_< z;WvLLgz>f*MFlxDwmvo`BfEuPRf`=G`$&``F@N_`N9&x?QNkN`rLLO6%|OVPWZq&0?tJOS=?D( zd0EEOuBub@_56dgU|w@0zm))X30QAK&TsXuSEdcb^AdG zUmKF7oUSnwS7$z*Be`x=ru@L;5_CK6o&vtiZTQDgg9>5g_ z1cdc3gc$K(h`)yTkHP(lfuAAwmidne^xv2q#@}Pue|PP`guad<0_NY`fKu`Q#=PhK zJ%;Ufm5=*Hd(0nE_Fpj( zQxF_=fcU&6z^MN{sAc)zWBy1<{S`Chkdb)<7*yK-IyZx=zsLNsa>1{dnP%4RZNNyv z0Vu-1M+Dfr(fkYZs|Ef6`mH?+oP!A={Pu!jX#Yj~xB2{`1pc*C9F`3GCfq2D!dko`m zjrmv6_}`q4`TxTCt>OHtefgUs2r%+LeL25e_21s3zs5fQ<^&)9w@B!(=jK;W(%+1) zH-GizAAY4@oB!MY@ONV%prE^dbm2eVh+kX(`?cwxtr4I8(faR~s9yp9p3MFe(Dd?8 cz<;K;a#G-cM;Z_iKH!G|FlC7Q!!h!I01AeZu>b%7 literal 0 HcmV?d00001 diff --git a/pic/UML/CHS/类图Siemens.vsdx b/pic/UML/CHS/类图Siemens.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..623743c7e2e268f70c54ad92fb5a2e9c424e614e GIT binary patch literal 50662 zcmeFY^OGlUmo54!+je!?Ho9!vwr!)!wr$(hW!tvRF5~of=AJj^-g)Q#1LtH$WMsyZ zzw8}rJv;Z>E9Ip?Kv4nU07w7;@B=_tHmVW_1OVXweMA930&5A`**crpI_oKW*qb=% z(7D@K6Bd91Q{(}F|Gxi!kN<-+(3CtTJHUV{@+|%#bVw_?nNprtqQgLwA9)X?`Z2FL z7-a4C=9RM`Z@vTsW0FWwf5W@d^0BSol%Uc8xCmC|JTt{h@TX$Iu*^t|9kW^|4}Xw$ zP_+Q#)CeLj+&dc5Z(!R+R;Er(On*L(S5%wiXG*mIffkdrA$@qUC|#`EPm~FG;>zaM zG(Qq}U4%ej!sQVfJ5H9*hCZM6NDu0EcXS$-r}|`MZ-;CZ2XFrn3Tl;P8DgVJ4VLH$$o+o zD3-F48K%|RH!x0s`jdUh0pzxGU@(7-2VzN5A7#r!j6P>Y;IQ>`zr<(I<~^+Q3F-NY z`0a`qf1MwbCIH@w@~6?IRo|=D^8vm~dC+ASCpu$IszN=^7^PiRnNel*K#JiWf>y&u zddnZaGNm9<{ce972o7blR^h6TJAR#%0)HC<|JhrPTXk1PH{A)p19mou-KOj70s6lf z{Qd?3$p62HT&mvRO!}9|x*z}m%wHnwIht5I(bN5N{l5hMKbW=uCG@JqiN6F!{D;6n zM?MEdJi+pbwup*ukiQTxFC`3-_>AQ$o^I-)!H7sr=ID6wcf3q%x-@U3XId}|Tw4xB zQk+6mxr%MH?pxnH?s_#y>YzQ%>JPo5ymfT+s&(rjBx4OreT*fBh7;U`zZAkKxLFXH zPv%N8hrvLSV)D`O4-qgmEOlX{Sp8M0~PG>hao`L zAj~#3U=2nuKO7%RRgMXbp;2&Rglp=eL39c7Xw7?vO3Lkom0=!Hn!LrN4T`MEm*ygF z;Udjy(LFqj{XIptkKq`0ILWt$>nZzVOBWf+ zEm$?53l40XAbjvtO*!}9vWop`MvD*?09fz`0FeK_;cDSzVMlLlXXIk@w@Cg|9WQmZ z><)+H{rGmjLIpk;7=fjj3+;r~`7`31BL1L7KMi;kntHNKI*vk(&DDIMk{~?0dPv

Si`K-|v4Z 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 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Class OPC.vsdx b/pic/UML/ENG/Class OPC.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..f86a889b65c7244e092131fc878ecbe21cdd838d GIT binary patch literal 67802 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 YvD>Sz(I`jq7vd3nZ0=1PCXLei&nhG(7e z5J`*{8odJoA@DEv2#v8M+%7Q3%UZA0bxXeD_KqiQD^|)}cn}&hu>7^Mhm43lMi*Tx zR4(hS9$;?({#P+*#%yh$%S3}zE8k5Y)Yv&swJ`&b4B}HF#6Fw=Dj&>l@s>;@iZWMr zmTX}1d9$T)on(JJN}IT2+VCuwQt0KN>pW3p_soWh=m~jPdpdG6^fXKAQbMl?SZ!zM z{KIy4VA3@_s*-%78gzozCqb`)9Dz^5XYaRIyWZfI*40?VeO<09+*m!*5LS^VA& zM^OSRHZGphzKrk37Qd$50}XURZ2GCW0{vro9FO#! zt#H%U!NF-z57Cxtf-hzW!-%@qYrHu3rKTu2vEv!SoHP`94+;|pf%Ww(?!tNgBnsMp zabulqkf=lndGy)G4W1w!zgQ*ew+(AYb=*a1I!%8=WK6CAy@r_F0T^n2UsI}c(z)mz z5MC27K@gYw&@K`&wF8?Z1h=cGfroWv_|4_*xO|%*seK_b1f0l8krLH`ib(Wh?-;vw7rA*OR$k=S7k6lFRv;~*@)Vt~j!L`Q z%yETzZ)OaC>BGu#dJH^<6^T;pO~Q4>dxFE?3QcNSAD1^^;%*^@lq%s|Xz-5!WCj#$$2kq(Z&F|&cI)QH_ z!RN)vUCDOQq|Y5&)dnooQ9aSG3JZ4o<=)UJ0Tq#{N;Ws{x+$<#8qjs$Fa%D^q%svK z-raH*aw9JN@m~w*jR>y1Po|q&w!aFEV**>YO-k8CA7}t!yydN)y9&Ld-40~S+>b~u z$)r)YnU`|C(@&?0d@9_}8a4t@zTsHj`&>@x&N`g|6$1+gv$w>E?HE1}9>?gJTu5YPnyW>VK?whvS zU(OYHn>N*LorGJUYijP>*Zw>{dQlG;rWA1NHeDf*^ES^y5skl#NS47T3SXsRdf z?DX|3Y^*HRyYrukx7zy)$cwT5h)anCa7DcAxuBa1k;|3}DRjN>ef7@hla7yp4Mz^V z?6@!G%Vr%hbn(A^oY6E&o3yBP{vm|xp%=gv(q2!Df91!r)6za_ML>q9Q*!WXF zDX%R`sHJ>h<09ps&WeZbCSyiNnCA#X>iI_=ae~9$JDq(vn6#P~@BxR*p~p4tH5b4t zp6OE#Kercdjgl)hAU)ap1WW9JI>wqmqtywNs7ur$tKGxmqzo^ByBo@zp&HlbYDfV7 zXjv^7qq8Zr0T}$72U7!B75f{A&!J@0!_Ke!+R27@Jq#pz@pwxFi+3rfi!s%wJo5kWqzz+ld*1qz9UN9`#Ri(& z@Ab-7#qVoar&w(oQImw(1=Rc~UK_cfc!SMeLEEjNcFw$lOMN9SXTRJ?-5O^_N0Ld5 zEd;{dS=7%C*ckU|QodJAH$EI&S)3^=H-3O@R;10YHO%_l51`ODyvsRE*AOM~E zhb`_O>g|YoVrpVg?pAvdpfsQoh3;|L94g@5QhKW=iBTEXx=2h$2IBwed^GPZRKSI) z*@%A}4G$-ugw~OS9ndi_CbX?Eg0$zOsJU7`Q%Y?- zCX?;L=x99>fplp;zF3oIGO^m-!7EC1S(emk&S+Df~*wMyMZ|_ zsZ@(+i9kdx>~yTst(!<7PApd=sRRkGZz7`k&nvn|B(XGr&+RcOoX?pC&O3U**9@e9 z7k(ts7IreLg{n-h&xJW%MHu{zct7@|G4C8~BP^k2D z(Akcnbj>H20TeMkdIA7I2Ws>&;6ixssS5VA=rZgi+w4mhJh|YH@sIEk(dForGmpNI z?PQl3aU;pUcK5az7FD-U6Jk)DoGvNf>aXkreT+c;d$w(x*FY$`s@I*jp+|VkMqyMu zG+D0wz(D{qA{`|#Sy#7ICGBYSBmE$C#ndnZzAbe3O3K|Wh@t`d?Oy`1VVy3~VNkp} z=R&P(9=49SDH5o~1b6Ci_eg(VOQb6so^P$A;;KOhz@LLC?ju6|_?lecE6OLx0|jJc zneTR1*9uf+<%!=#4<97@1##FT@4D`^nJR-9(U-vIN#MV14cOgxS)2YNH~OX@{(nw1h$@_58o1hpWmeB%n$@=8W=134wmu!eq%m5>zg*OeM7 zfK*8b@QarZ{?-NqzHSF9*GhmY>@V4ZTp7SMYHC!KN$boX`QHhDcHZ0qrSe&aksRT4 zX^dkW(B@>n&n!czCvqiK6{}VAdz0anX@zwwG@*A=ux_fCqCJe_8Ra)tWL7w%L7Hdu z@@SDOK$5H(9HLK(85_k5J@KW7QEV#zFq5m6xt5702+Ib8fjh!DbAHp6fDXP!E?i`% zDAO;3MyQ)8TTF0^JyJ7=0c0jAN1+R_`uAs6oR~s6iEnBAjGeir_;a@Q;(glhBSW4I z(Z7F|)j3j>A8rBZShUKWz|Um>u!ibUUmQ(OkZCH}=T7iTd=AcVv$P(N_p$&66AsH` z>V2`f%LHlLwQ?i(wo%B7UMux2{<`Ce)%EKcEDvWp4mYTUS~oj;znXj^XZoZCHTK&I zg|OMDUh{O!#+!dzKUd`q{YARW);h3VXmo8LcJGzf8CE;a!6%=I|6!H+IzjFNdiTO1 z(9c0PnSuVMbuJVUASToG&I&K3U^dH?X7nu~Ur;$mhwoEMzbnSm z|3HxwrPr(Jv8gI$TMDdY_Kc)j&@F;3 zdQ|cce>PT%-swxv%YMGc;7%Ue=Aj|iE$XaQpmsk|09r^f-{@>dQ%Aq8+s|mA%bGJd zIbY)DO(~%K)5j7KK^Q^Nifyf!6VR4Kf4&?<%O(nwI=kdrlc@~N&9dZ z(m=;XKpmWZkdN^KP=sNUi-^c*cvKOVl(1k?9*GG(d0UO=iT(3KX)*@OPd@>I9AhW>wrTXfdOU!zvd5=7rJhNLln(IjIf;t^w|P%$xd?35|kk`QM(4YR`G z{J(X7Tqjt@tTp>Y#$enB5%qb%1IzKb(S|Msp!H2sE-#icvbCG;3`^4YniqcUveaT& zL=;5k>(5sMl4~!tOV)oZoN}F0@Ghl8Ehju~gh#`%gRjeCm}?6rIiOjBRAmV2o8soW zzlW}B6s&)@-_>~5S|+>yk#Eg^myjm_8$`z}(LrNT;Pa@rI1&^0wTA493wbDe5>hhw zs3!bECju*<9reF2e<^pkHt>%B5E6Zg{P?vi5rVQdnE_t_0rY_6BpJRDyrm{v@@1HL ziv4E0<~WGw_Va1v52)v@eb>ST;G^d{@wcV1(!%lpnw!_*gznV24*AlQg}v@DYj1OW zS@Y)dLzpiHb2{_0Uadm{K=&=a8^pHNY=|Fg!|69E)!&@x(-aqHONi6xBXqz|6`&gXzC=Vjm_yHv*iRJQR ztrd*i(mtjM?$3vpxx3V<&acap0gc}V?=N=lYQXzIUl7E*roj)4$f$+!kgN)3{mzCV zlw^|z%$y{o{{1?#pUbSFoI0>Y`2HlTpt!{E(vFssFUZZSpid52Z5EYTD9eTIYoZk zy5=Z*pn!`2I~QY1saqXhZ-*}f7``3vj}r$1`q=_sd@$@p5e;mQY*V@+1_aC$2deTu zkLT}WTea;{)iDdkr@Z$3P%WS~frLp0V^wvL)ecTF{m;TFh!2OGGwCR95` zL2%T<2Ew|`z8#Kx`L^pI&8bU9z|tA(lfHKoYg3=Yj%RuYDTt#F;T7wDXU(ycA`_aC z@&g30)F`F0o~ty9VLDbD##H5!Pa;b+8pV|3naEbO*Y|}}rq0=ke8rJzu*oXYwF>q< zjRyUoU9OhX)*0l}qeJK}!b%7|(}A_-L8trPyQuhr{8cB!XJThi`2c zu;=Fi!6#0PYdWI_LR@73%Z>YzaRw)Yfw%Wf8^_YmWa;&9ZPzcgZyt!A4{reLEZDEl z+m{0j->)s`TdT`tj6KLpeU-EG(qyoN0kute42(1-48KN`xiuo$YO^^70Gt z3q5t6ZK{pQBEPyz-luxrhYdQKw8*KUN2FfYI-_A{ zppa0j*6{~ci_plaQ6EkT8MMpJlXQw4F8uNMi^=0sTTc{$^B;mDp^X=Pm9(_W4gYw% zCW>VkwIzX|Jl+pX(%jcGxnq)p8gk(}%vwaoo^r8}mPU&stKbk@TV{a}?8K?EuZtt! zSVxLscnQ*ba03^Li)99h)V2-k0htnzn)^B0c&W2V`BJo);uR#{1!&qZBG{UO6jO{? zD+dPonpQ63j*ry&EJ#7ym;>W!a`Pr|w3SCkplsJ?-5K8W%L44eG#S{QTj6K~ZK!r| zbcXYKx0%$&!>E2{MYPL z9lJin977%8@4My{R=6#C#XL3WCm!eH1dtV0PO_sdU6+aR05PEivzD+3s7sn-cYH)p z6dX?!kY_FoM<)x2H&!_u@YSXnVTIeattCN!z5&gPGXm!97Ko)XFdulO9MoTQXzt?Fu_~D zLgi+TfxiMD+P=Q6T>me09|1!4B<(xiZ~Zs%p7Vdjdz_(v;=R9;e?ooXfqskblC$6) zF#wG!xzOx(L{o{xVef#xMt4*_CnJ=Y4jPh55iEG-bwo@bx!GpGnU_*pD$Ck zY!l(J?d50B!#CgQ{!n&wCGRTM4jnqN2Qhj)oUs-nhsOcI+h{um`f?|aO)%I5#t*|( zDFKFL&au|{N{*ps4UYtJ8^3jP_?{x*3=f>p>e7%KpLWQqKqxl*27r_Dacht*dOHTBbR+0!6$Kb)wvwl&x}(@H z(wS%$q&y14kNmnEus<*e95LiuYRg8`fy<{;(UyJ&k5o+GRlHFOFQ;(q7iS@5N-K`q zJ=u&vgxt6G*UsjrtB9X95mjBc`&qoprAq#EfQsRSg&2VF^Ke2#r;p)wj~URz8Q)x$_TP(m8EhX{u|;Y z6z{Qph!=FOS{v;N8nOzWB;h|H8C3J+8ExxnZBno~iPUz&){SGo3*P3PX~XmO zyC`wSv8loY%z}}qP&jTaaCsa*_u$f_(i2LF`z0o*b8@-SYik|hovaBSk zO)w_=M4iM9!??8C1?aPfn->_?dNw2LNM5F0Yv67@)KuV%U(A-M`ha-MhXtHMboV0X zL`(D)jFBQ8o13+yaf|JVr<12R415BSjUC>M#cgcG9Hp*25MudkyBV*UL=tB8Qsmvw zMdq3{>T3QWLU^`~iJWE0g2~#0u*I*Jly>}F6>AQWW@?+5{dt%fUkEd$d=3q%({nk2jQRo0f0<=+gSQ@}LA z_IY=(H+Q7q^S*Pl!eNl}@j&pO438k%KLTxSKubA{_hjif8unufR!KT5)zp4a5+uAS zy|BhC#y$d5nh!#v9+Fd(Gi!f3>yFIcCFHV?ytF(yB4}@mH~|Yq7QBDuo>;H}pJ`c@ zu-4B>vVl^V9im1<`Sc7~RHizAmEA}LUgG0{(6u4}nRC99Tv%ZgQtMC*OXX~e0_gN)xeRfl)R~4ZT|82-+M3iE>~s)3 zKy21;Z~B}x8B9+xx0gyff@q8kYm{D5(cV&1NM#sElL+bh$PrmtPcaxQ20$r!%)1`? zL?&*KF`SN^>h_qLdNkE3;Qa{ZwZ3B4Wp?2Q0>Cwi!{us`fKMIYpx-Mb9EJW<OmD42mI0Xt zAo}x3ZJ?)HW?DhH#I=*FPS1~l-&(dEW$VboEwD8+#^tl+Gw9zjzP1_tKQUe=>v^ky zPQO*QK{cJ<^L??=y-8)N;;$+Z=uia)Sonu0leCpSpj5!4L?LPtDG&*5Co#eNwzM0YKkKQ2Y$NMvZ4*}c@W+Q!GL3-q)p*=mB zAG^H1Hy0}e`g*l$<#o2HO`}a{|5Le3A{SRO^*hJ+Vd{xynDD_{?C z`oPWCA#y*Kx!{nB6(hB4N8pj`%FTZX1*WQDxJx%VCELs=ALXbQceeQlOwz*y+1PE* z79N;mGY;gelIx?T);#7FNUGD5AH^qB9eq$eF z-;@;?av*0JizyDJw8wuw)*E2s+^*b3eg(KYiEo{=A&KMNm<&1!Q_;7A-441@RqI%1;OnA9T<{17 z>8-Y>GCKZ#I*oy`S(s^Wvg783D+3()``3}wzNnuHRtN#CcSNvT z7lR|J)B(Ru2mKS1)|w#p2*-dvFo%3O$eMp?<;p;l_SSG<3n6T2oqrp6QQl_@RIILb zy4JTjFy0{v-h<}jyzt<(rd;sg80_DuB7B!-5HHgqPKI1qbrrkxdn_p#B0`GXFyVGw z+y7!3*N~1Vic>}86{}e>qrluOgKZUPB`3km`-c>wvo#c!N6?q$3o~#Ftqd>vGpj(- zhx#lK=dH`kJLu|3YO-~~CRL4f*YDo8!s^;Dv9i|A3saR29w*l^e#YH$th(MrDCDTz z0K5p&xU9Hss0uT_I!hbVK`q#g^ue)KlH;ClRF#RRe2^4=m%q$iDI-JcANA?2Rz)w9Ab49f+ zRo{pRuO3uxeYp$<8LuHoAiQ7J8(b+jo-+k%r!1*+BNZ@0npqS}N zw&_ro&*^kRh4Cl1fNU(E-Q!J9j~635#UL+74MZi2TV=<3cRDWT($Zo#ue&Yq4XB(_ zLtwa(+}zLeAzRaW7M2phr&R}v5RNIX%V7#7H;70;H8`>KO*flOU*O5)(Be<|GH>4B zSfF=|d`=TBC;S|9u>=o;gX39mzA6?Eef2r=4|e9)^WkT-<|p$lY;2yJ(Qq2KC-XIC zYws#sUMF+{d_JlyHarX5vTlD*)VN)w_Eo7;T*wTRk`s#0$}{BkaEmi1?)|T?QEqnH z^UEUCsig5g=dnFZzD^ull&KG8iXtkLojZtsz0TK*o5b>0?o%HG6#x13x+NRgJDN1) za&qrfq)b(tB*l#5=9iuOaZbgB#}EW(VXfpC98qk=Z4nV#_bYfvql9G5G;zQ**2a3U zuq=q-t^N9-lBw)&`*J{<-%;SlpOY5J7RR8y?l ztx6p-RYi5qpwl(vL&-NY4Pwe`k63p#TRigb`&^y6xF!|OHh1+M1H#<);r9P%?<~CP z$eMnQySqCCcXtgMEVu=i;O+zq?(Qx@g1ftGaCdiixF<93d^3|T@BIhvJ*;(B17|;HG1RBt=EG+h-gPaUTVJ!Mt#x5w#ZDYL43*J-OvYtgjQ>d%_FR7~%w^oVOpwfVDE>$ND{sai)d zP*$TN7`_#4G> zXhDqQtJ3-HyxW+-dW8E3@%>8=3w7Bn5&n+qGp_?EOLnk0>LpmCGKG@5!J+!m-kf zH&7zOI;&Bgx#O5$*ELArCeddX_fF`U-!>77cq8%W@H+S58>3NFhNAQ9E&R}(2MpNy zotE>ipD4BwnU#T8;9Eh^-V))oqfpRdO^W)t&+UncsfvGG2Z@3UF!%~&ZU8N@7Q&`9 zwmw|7w?FM>TDQGCj(&Q*dJO&4{&0z&0FvANL$@IQ{TrvfzMJ+HH|6C$#Nue(qUWGd zC%3tQ{rLzUNy>Cyg?kUnH_ho;-@RyXhYtqx8H*hJHqvj$iV|~TLep%Q zti9f;e(`*nIb-U)SzI5(IRMd?$$@_5+4|uc zVLK)+PdUdT#+Py}2(!8LxIFy%9O(I@{5s+yyS;THA6idB8c zplJ&PQSBLPwO-t2-cO=ec=lALOMK9M{kgg%KFg>UMyfWkr=;0YE+|^)p;88JC`t}p z{O_$UpH$mjuK+=Tw^O;bFE1xY)~~mZGngKvWz60ORc$`#1!HAFiR)wh-rMqS(rmTw zWc1w01wGL#1arQY@JrHuC)Xf3FQez(>$$FkeddgTWt&cj_3hwRpNGJdsxZW(nfI8+ z>lX!IkDup7^~uU0Y=Nq9zE!T`;>0tBPY#W|gywdatBEk5U7~kIKbIZp#q`l-I8y_& zvu1=K(gm9LCq(KR%Ysbe8D_HktZ=XA3E_R7VEbtZ=up~V8>jjL2Et@&qjCqO2IdDs zf_8{Dnu~WwyzO1H^!kVQ>(jOZg;)xLAk&~big0;F#@PuN!U$Be++!_n@G;yP^L5zi zh{K)@a05~Okq|6v?Y?ow&u{9zpdV^MZ`Eql!J(*Zz2u>z`Dag3lrQKARmk>v+F~&^ z1twG^H+MmBI>#`B<%g6WE9u#ZNNj8Qg*!Svue#+V!Hvm)pj4gobE9cmyRq{IGj0p3 zP4+c3Q>YF5+;$Z);V%LuAWK4znP>-QAMkR#Fb0uQACN?8TC9MG*_Bvzspuk**jX!I z0Vg&arVMXl-5OQTon{K57P#BR`P5Mxez|t$XtwI6Uhwo(ov-pA4K|0P6AZxps5mP9 zIm6N&RN6Ze#_i#NuH)s#sW32xC8CR^r)8=`&9|+Z9Lm*vqGv6OGP}ERo>??%8`ceL zLZnK4O{s|$LZ_#MH&YpUUrHL1BsZ!%VoTOr1?N0RLP>Zmm3dbIxYlvi({P!jIQt

R|&TS#&tt1wHh->t=P{mDs(FgUz_=NZ^y;R6Rm6c)O%b2_gYl zn(~^SeMrH*O#8HH1AIX9LR)0NExFAB@504GG&uNi&VhqPL#%(JC6{>hA|2P>H3;h| z%|lCZiA`O8R}63av5D|};g2i)fQm|?M>Ra~n);V-(xFuq*E4BjrjJi3*Z~ZY^XlNn z-*z*$Ne|5g3*C0rCnAfQ`~>CPs)Cu+^qVEc#Cj7baqxF5-mL>Guazkz>ZS8++co?U z&_~K2fQNOJTLLecqt+nb=7_}FQVW*GNK7M?rT^>_uk2AMdo~g0YY?LQNzoHSbstqy zR6;gJE#5GkxVd+z`(u0l;jK|lPs^!_EmLR=PP7Gu%S~ztT65SBr<9(I6q*-kWI|O?&H+od%zJAp7Al&CuOno_TFL6Sn*Aj>KI8}#*0CY_;yM2n$}rJ+x4Ui zwLf1Kyhxv`Hv1y$V=r34J)VC-_s@$WD>5~p>}{6Ow&7p>2gICC}9B+Qh#GUuQ#tcKEhaV|FT#i)@==zO+Uv*%+^2vlRl2CyO; z(R4itq^Csc#tmL*Zm3DB!nUVA4+9GC?Q3Fduxw+x@RvA(WdDTgS;!R+lJE_QRY{XT z1hb$8Z%Ahw%DjtB{KKfMaM>`@^9)v;+-yqp2s+cw+4)XMJ6#`VJEV3nNHqtiOP}hs z^=rS0r36_bOmEw&U9MWK2?z7CD}1yjs5k;&3t?#2 zWvx??fq8Fy0aVf%o8t|fG&ynU;s!Atnd350NPI(H14IPy%bSlVojcOlmt@GgOMY*&VD2l(SW9OqP}u1C>6R&USV@<~AfXo@sEi50Fq7Mo)UQ*072%X?TPyc> zV;y@}adRPo`Bh{{K#LQsHL*X^0s`{KJvs!}dTWr>b_0u`(ECo303!Q@wfl9m>k3Xa z?0(rx5(g4t3Vk!TLhk?vjWe)``TG?<5aeY-BIGqmf!cs;BPqfhiW^+66)Y_AZvm)3 z#^x!WHNU)zB#1>`&FC)Qo~*wz?Ya9jEW!YtlSBK6pu-5kcm28r+W-=mfMJW?#E3Pt5KC+#77}tT1mOlTi4M(6WPjz#OyLz@yi51gH zv18a4_J!Is^J^|Ak7(Uy>4Fsb)t1R5El|UX`bW{xc&X0{<40dTbf_llJ6%yw8$RHC zyi+&iGoQg#WrDoEojC?2hx{abj--Pbxc2O)jq+$9du^r;)l`BQdM;vBZ_!%u==aqv z2{|0xWzWRyOcZsuOGl;rPA;*WJ34XfYlBZUY!msM4H9PPB5Sr5>4>-l2PJ7iRKuBH zR^)@a=ze4UD%JvL9#o2uD3J`8kz?D{v-V%h1 z;>^Y>)clrz+OTG5^*438VIF#4kQmmW%~rpZ@H7t57L+tTC6On#$psO&fMBoCp8O4s z>n9-JE2Q8aWM8Gz6IiGUf#$^N1Fr}{r}W-9r&vQl7E#<+ZDgtJJoJ5?OJvc`mCYt* zdg8F*;paKDL8sOuvf~pnKyeJ$JM~rfAd`~m-t5G6P8{OiS>8uIyd{eF!J8`v z8A6nu5EsB=z*Mna)g|i|5rBeE+(NWnEHEfAyav!np^}xLmPWk7zLl5A${Rf^yHTv~ zDOHIlWllj9Yd**O@-m%J?haLr7}ijo#nL{P^~Xxp$G;{~wTl%f zV1)2necxviA#iMfA}eh!}Mek z31LAIYnD*eT(>l8d@H4{jznJl?ORo8a>2J$pk@T`vqa4qty2PS zU&j)*yR1}(fj=a1q(Eeytnh>Ka32zlbT39u307B9S6({!p&$&KDU$-I&0~siQ@$m^ z@C*7AZfO^?+B9%Pd$K|e+}@BsxjTG`TxvhLDcr*ZpNS*qe2#+&021D%Q;TZc1qs5LL*u+nLc50Bafr()o>=U1 zgZdW@mz&j7gAQXZ68%s|!M;KQSKko;qX?*1Us{|$76qCkQ8f0ss3XB_L}a@&rJ1!? zu{lpWMX3E4W%yI}hSFoqT%FE__J02l*_)2$x^}PKBO-eddo>bAG|Qn2X|tTp$--7( z^LHz`eZ+vwXE;`!t#9Qnxu{4bNCgX!#e!sduf#LtcpIYz<2t)z!nb7h zdl11ALJCx!j!Ew_?hJosPHBqo>#o7Xs~dAzaiaRa@GtbW0#_dc4dqSbN*1H2m!N4igGE}c>g)s`l2)rQO|t971X>u?yNazQ5UNC69=tgYH>R|v#J0FpX9JdfLRNDyM0O&}-~-HDWbjHJrX;e($4{#URZ%w~o5v4ZMkuiIo5Zi5 zK~}$tPVx=c2WN@kV0|ym5i#Ec!#8iocR`BxdCv&-ak>IBuH%ggiKsgHDc>U3r}4*o z&tqL1Rs=pou&0DOECF3UB;N2G_M0M-;i<1oXzJU#a7?7*Hy)QTB<=L*{kb=EyfhuiqNUlvOw7w zOuF(-fEQ;4EGvvDC-;f}Y2&HTCJy$OKSE*bs)HhYZp72fL8L-0=Z7c~pFQIPXxF4B1W*0%O95F^{9i6s z4nj@V^8i^>@FmM=P+Qf+-%Iz{55b#@gNOU&mDo$KN`9 z(@}eeV4hM;=)230MkL9jV>1PKUJjjUt#{S>KQlR^aZ3B`6BgLod6Bmd(RT%m&>@?s zGMW*0_!Ji?EYVo+>0(PmGmvY2=--!)ihnV++uGbM1-D@+?*f@7YfOK=U8>J~3pVO( z9&a}?VrzEN%v8X%DWm65yRI75cx`NLyilB3P znncDy^rJF7R+An6K&XT71`^?=X|V5dt;f+o{d+%fyJb7X!#aV27p=vXZ20SMfiSRj zlX{0wvkpB1%sEGYW>Q% zK;Na*S!m$Gt!QLn!iDg@b@x=JgE4+JnaHo;?Q{&xA!;MXUp-Fuec3=t4mHeyzOROU zF2&DWDaD_;QU%`|8|a#fKhG?_f5njLb7kvWQ6+i5oX!3Ls0=s65Y6$!k5SS4)*1G& zdgvzD4wHAIF=d!WMc=3j;9{RhSTlXBaDsPDMzyF$N3_L+6w!L4Hj0629P~aTYOQyS zge5@(yCUFlXj3#F#KR_GZrFB=r>|o&am?iZDQS#JM~>d;TpX_kqJe0(kUZ-ry6@5GsSq2xXVE| zd;~fi+57zYYwuym{V=sdiX3=I9EUIrz2GTQUO|JE7iO|nQL^DaV@VhH;R|N^RP4a+ zQH&DAPR{LT3$5Nnoo{?lKSl!Y0eMnsAIM4W+hw?H5`OB^&ChFVI3rW z{5fyCh~O4hHP3&BxL!Jz^#Yu;_v^iSC#{K}-yZhgk@an-+6*+6rP{doxJyg{xu7CQ zFXUA?pd#=kHs3nHcW0+zAcWsxA&7M{vP#kq1r$g$Sx^S&r;Nn;y1e&2>o1iW0;d-G zsOb2CO-Y$bs`#4>15(x3f)O;|;p|WK5|qw+FkEGfWJWui-12Qjps~fnsoYWa(H{6% z*y{TEXbA?_Ug~IHBwlz{oGxPIbmT8boqdy!{E!vPAhzinX^Vh&zOt<^%Mol!hf4kw zsZn5<-q*u(ps!m@akYXd{SYP)&A(Ft*5Tj&{)uS26Y-9<7qE(Ia#h*>XQs*qnUJ5U zQWnSzjSK+Y;-DP!yxU~~degDEG^}R!lo|%2*4BG~hAr$%s|_lMSqb|gGIQfN`EJ<( zv3xqBPYpJVKxRZ!&IRbJ^SbjJ=liYRPv!k%5D!kY_hqOXSmh|4onH9mDrJ6$i1du*9HK=Eca|LM3k!FX zoo0ABK=)-f+e?7bQl{xuSbBS_kd+;x7IUQA3(((it(O@KmRI|;PqO$4-&4My1l=4T z9|_0L;e6ShR>(|r9dm>839-6Zo`#P~=5?$1vE5jCxZo)@J%_fP2+l+nIDReaW&gSMMX^&i3nFIqX3IA`E+gJ-M;UB7-9F7aV1HuV$BFEV43R#!t6 zYfV!_H}`|mU^_DJx>tcsE1X}*rhsWxfn^+k8(DfU*NzI#RgT3oW`hP^xnwb<-MC~{ zzxds%WTBv#Y3EK3!M8RrNz66CU>rUfvG-+1Ny=+Mu<{As%tgHm8g7i1hKX!EaPk$G zrLKaX5Eo9sOz!w9gKu}3&lub!;S`?(IgH8~!-98%VF&oq%i#!~Z>~{#MRL=YUDYAy zA-q@>2Dos`)&BzK5YvygeAoJ}!+-at7QeA3NIu6YBS^`YDPn?KO(Pm#@GCKNyPPfd zf;6VmN06skkzu83tw&H5=V|i5y+M^R2JltG@s8m1iXfWPY~`-1s22%upD$K|!w$vR(IL`iF^&RTn_tVh8Di)`)W$l@JMHf9^}`cSvOX89gXkj_~> zyIRrmLyz@+xsujAu1Rs#4&?L*b275J>rqal7EeJfv`oe1=urqF#UTXghtIm7@?%Q8 zP0Sa>N*y4!3}S^)RL(xYx`%bW+=5&*2mmaI9HE8Qy;>KjwY182^*x}26q#+fCak3x zsncs2g$WcqyF++#J<`Oz60b{L_DH*)c)fj}K zDoP0ZHUts2QnYA$IJf_T^PRzBFCxrIY_v$okY*~eNRwzhfw?O2P+eCigb^1du=-%c zh5ZvfME55Kcu%Ea$6QPk>COU0<&FhL-!|EJDnlzek=y)+Z}?O1({eOQ$V^4%%}ony_^gsDp64afOpq(fH|V;kG8udZD)BgUTvTojqB4C1@pS5 z)rY=i%svTkWG+RwMjYFKYDwOxVtVR~NXq-|%!h9})XV_6hqhvGY$vGo z`v4;jrbTj`OXjwXC_lvn{UqY&AhT%=3toelGTR6>JR^*siu;@&7KlBsx4=#Jne^PG zPEzZ0XD@;P5iAQ|ewuSVX7Dw?c#5uD=%9%>H!9{SwV{Cd5s@!e9r`3El5Gu59NcR; z#=>*EXu=x7R8gjEwOq;y_k<5RWP=K!_^rS|T;%X_z&A2lm{=ErwXoffV{Nqg5*Qho zTzWV=>-UUL>EY(*A^BqxM-DFj_gQP_2)Q~QcXqD;KhAF)ITXg*K3#xvT>i2^Kp22e z7+M?1+gaP#GdP$!TIyTrnOV>qSsEXwX`3oZVt89GS8R}$~ zeA*X3Mh(%2giLyR-E_@4)Iymg!`!eAj%fjgj3KOpb1mj!u8t+qf&K}j=N;iAF#|0B zYFb?X_V4M7`^J6+OPYw-+jt zUr?r2cDme{+dqStuUMoulqhA;ZLlAV*viW0__d7wQ(LJcd5Vyph8T|NA&ho9uPcf+ zy0NjH6>;L=wid_S$_d7@R^QFKO!m6|lhs<=idMN30B1H;P*+!1Yd&|$?lV;QTxZ0b z{ONwN&2C4^9O2N_1SFgn67`XnwR)(=>&1;TD1jkx=mz-iAq0#o7_jgq`50Tr>wN_a;1aDaGNx(8>E&&8LhX}<>cWze65cYnt9Myu zNMfpxhy=Wzj}F3O3UFgx%N81=8{9!zW3(zfPRD{639=~c42gp~%UWeT94xuCS!9)d z`ytseEtOIqr3raLgY5Ul^xX8Pw)!JSAFI*VXP91VZMXVvZ*Mz0g+7XY`b3y{$$lZ1 z!7HSCced8&T$pYJWE+Cqbm`$)rQHS3d8GuZ>y1&M$c1&vicB^9h( zq7oh%Y2d8ySZlq;U+{ebT&kQHg~}$@nN_oRdTQ#U*@p*bO%s#guZ>D1-weKvq3$DZ z?f7(FOP|}lK0ma&-#Ixrh+c8nAAs!Y#zb`3es3>}`>F`9bW63iR-U3|*2b!?qFpV< zTxMt#fES;gSGn;#J)g9P6F02W2t-Gox7ZbTMeJ7QctT_zEz zBs}nV6cTL#pVT2|>|a!}eT0tScdwew(h@_=k}h^UnJa#Op^^M*^q~r?%#lE~03rdT zUAw@ujthT4<;B@pcM#l3(tlnb5chZm|M^8ccI#ojwxY|k@m=wIO#XvLs zQ|G4ctdA50lk!r%^;(4>-oTlgoBqjqG^w~+ zX%>tjZqT&3yKY%<>D%I1L)T`{qEM;8Qffh2lDe_KFb$L@E!-%V`>h3xww~?$ncWHq zLYq{X^m=z&VydlCb*K+~!I(J@6O=YpT>yvKQk`XMYpcHb<6|2TQ9-lQNyvWTvYk-o5Pi6XVzsI zwFefHu_P>A4Ev9&SVSyvjb7RZ{q5HZ@89Q2;=<=b_B;&N)YY|lJp70(FD!fhvC!Az zc2i797@EEK%FNvLe9s8iq`#{IvD?M4bvP7H1G|R4pIA!MvK)fL{{TNVbG0`P`b1gE z@MEJ}l=iFv#$0+HFV90wq)RQoBQV(XaHw2{W%ow{xVNeE)$S+-1##Hr3;BgGX07vH zd7*BCv)1V7sCu6)|3W&C*RzYR3M+~>I0lsYYtH#(liS;?XO=0fBoiHL=>taa0noi< zkPh?)sYDGYEL7^WN~J^QWK&mkH_LV8XH*gFWp+CJLMCYFi*$;ManT&rlh6>_c821? z54zZny)uPUqeJ(4ZkfBL9xyRv@MLivdy|S?-ejd+rUn<2TT(b>er!%qJHiq5ACeMJ z`USPkP^=;S>5$mD7htK@Bq}BHe7587B&P}Tj*|y036n=GJ|A^MW0mC=L*v(&%7594dy+)EXmxxIj)qi!g#gDH8msij1#kL|0T61o^4O zMNcwpKX=WAs=@;c<*Jk3O3jLh;4P$et)mo*Y>ca^I5;!{jl>iKCS7apD_7tg4ypHa zAT5UFYUN0TUg!J$JnruPUIbPI>V1M_ z5?FvJ)YsG&LVgd^A&`V>XsjP#W2Ht`he&d#d;4;OY^o@-NVF&guI}!EV)|tro1=#y zK<2ZhdY0wq3MQyzN3zJBiFkw(Wi3V3571$#=6wf}XkyqBL^W!9wl-)V$k3y(kQ%+l zN>s~t=X)a~J9Ixcg5oK3WP%UoSk*xVHanjw?iI>qK4PmxZYY85V$y3t8IpVU@UTyU zr+|uZ)bWC2NvHIz`T4ke&NggTNLpcvhvvfViE5|_1I3VyAk(4Z5q(vV79v6Up5O6! zy{2p~!!y7x)Sg>Lpa;PS`SS9jk1*XQR5@^IwMx=`m6o2Gn^q-%j2SmQ3S%U&?fdmk zRe0ZrvJVfjawXi@>15F;259S~2PK2k)^}JHLoY^-n=hf!2(mpjoljn2dVU%$mHCiF z{b3W&oz)d*%&u^OMBmNH>9d-)#KY?o)tN7=ips58)&A1Qvv*|ES_3;Mu*-a)-?_zQ zSQ=jyzyk8opAOZHj0`L5Rx=}YdE>(=CL?DSg>Fo!@J47}??GB%hw>83w-kYkg>Fni zq$GZTE0?K4Cvr|LD)J?u75788v1eT#v9Z1_sqE~;ZMW(A%X$naYwn7o| z;=vlO%K(pI&8D~!LK0`2jR5X!agNmjzmYKW(B6QXh?-a0IrbKK^>$_N`BVuHUz93~ zBl)2?PBGRB-ar^t5sX%EndJO+iUhiTGCo&ERZiWoYee z|I=w=p*S3o%80h2dMHqFRh)E33iAHMFiz!=ggRHY`MLwV)HmGXUGl?|4$(x-M~s2H zv?uQVu~VIZRc^l@S|Mo-bt1G#@uiKX_IAvpf&OaFy-&^ysF<}arblgiL?fu>9|9kW z0>NRgv0avu)5!EhX^*KLWVsFc@bjAvb#)gBT=Mf0!YgUG5B0xiV|u`(x?GTFXaie|AqPbuSzRo~LP8y1KOs_!=3 zbnZvK0g>{NKco)wL#V|YHCEez6=is_^nn1AIJW^!eLisci5|+k%KEl zuiHeg^=}`4qE#_T6aZz1&KfiIPU;9UkMTV(Ud15!h6Pc-G!WQAsYimG$V>=xP?aF0 zjk#o+yol%_>Tmm9i5k~bglLnf5XsQrZAk4P=#AX*Tl#c=YPb~wh~iZrI1v&C~i$yq0iGTKgEHa9Grj zWm9LlrY=YsEy0leZ8J4{q+13OD#QR^q-HAc>=K7f)6{5gE63WSC&}2^$GW3a$ca3)6+vLea zO*GV(_~&dq**sa^KN#^o7t2Vz(WP)q?>E2OkbMLBW=c;zX>0vvEzq|%tu6YJetwV< zLw78|y|flC;3=Qu>KRh7yzMc&?ETD+QWDjHp>Jo$T=M<}D5ea~Xck}Q^y(%{C^7as z-&)fHk(#+k0G_LC!96XI%61o%T+DLJQliX3OJ-xsY(U=EG^*ZAps2*GWCDp{T1@H7 zRINZWIIQZArZ0et?SIQjK0|)PvIAUXR)G64>OU_-14nxYYs>$CCH{T)DUH=O?_$IP z6tR9nB)_XQd#p{U%c=9N7@X&3a3Zb!z&1ffF1ccO+|F=_hTXi_GW^u(I_AT1ah_h+ zhXE_eDecYY-O*9H$)a9}$EhVVh7jRlAzo*RN8ZvzproT_{_)S9m5(E`e!;iVXk--YttoBN019 z9BVsXq1BN>7-HG;dZq3Z!7M$g+73EEas~h~4NpESE^Don%G*MhXUYRiz(N1trW$2_ z#gPjzRro)q4*&SZFtD~W`u~Rdx1ol`bjmI>A_bhqy95s0mBzyRD%ap55XpK+H7S>@ zhVdC{qbyaK;MUFQG~6n4+U%H_e)3Zf^w%zmce@&SzB1Y!ACWsr3Zz0cr~hbvPUmPHwo)iQf%B;mzC$MRt`PQD`IgXFb@z?p$sfXtB*0AH{>I zjKSq#wQcEC$d@uJB;BVo5d%ilNVnQ)xLKDECs47AKS*|+*HkJ=e~^rs zf6<(S(M+VWn;ZHG-bdTD7tk^tfc^ey*}x!lKxjY^K!8~?5HS$ihWu+0;D1g4hcN2j zXYxN=nj+R#4n|fEpOjo}jO?|4+Pb{-zX646UA5!@fDYi|0H_21@!ACZ<&&L}g*^lP z&-Y&&lBS$<7@+|H4fp^70SdtVTE?EiN=Ce}YT+4$KC@b!ZKkJdmy zqqu*y|8w{Mr2MukWcmj-sDLr30(MOHFVq3vU#P#9toRf8pWlA=>$k+n?&RYJ00|aA zCHfbUpWrW|jh=~-J;R^8KeqoXZNJpbcpWfISU~^K|3zaZ{5S1?IKLk4?#i}cGC(|l zI}8X2`(FrglD`mt4e=j?`xOH}L*XO)9}(!kF*!`X$8h}a+<^&y8ASxlzj*+q;{T0# z$M<^-`|mInI+d!$04qC%`xRp;{CmtFD~IO_oMc}sv%|9eo&3cttvk&^l=X2>BU^9C@ewEuN%2GxF#`D5jRUokVyY~9;{ zk%R+KM1PM6uyv#L7v@(B`~&n`dlozg6Gr&$3B%O+i}r8x`9lf(Yo|CZ8TUe|GBU`)|kf>w+?W5A8PNFT}rl^5^n0zjo!+yC%)V<4cQyMJ`yKi-I6TmSp9>7T6;pZ?MM?}w;g0so%N{u9vj e@=w5jrnd6Z;DB2i5D)?2hY>Jki2K7a@_zu?bBf0R literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Class Siemens.vsdx b/pic/UML/ENG/Class Siemens.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..d4a326a7a1a4e02e3e1152c636982e0e2105118b GIT binary patch literal 50662 zcmeFY^OGlUmo54!+je!?Ho9!vwr!)!wr$(hW!tvRF5~of=AJj^-g)Q#1LtH$WMsyZ zzw8}rJv;Z>E9Ip?Kv4nU07w7;@B=_tHmVW_1OVXweMA930&5A`**crpI_oKW*qb=% z(7D@K6Bd91Q{(}F|Gxi!kN<-+(3CtTJHUV{@+|%#bVw_?nNprtqQgLwA9)X?`Z2FL z7-a4C=9RM`Z@vTsW0FWwf5W@d^0BSol%Uc8xCmC|JTt{h@TX$Iu*^t|9kW^|4}Xw$ zP_+Q#)CeLj+&dc5Z(!R+R;Er(On*L(S5%wiXG*mIffkdrA$@qUC|#`EPm~FG;>zaM zG(Qq}U4%ej!sQVfJ5H9*hCZM6NDu0EcXS$-r}|`MZ-;CZ2XFrn3Tl;P8DgVJ4VLH$$o+o zD3-F48K%|RH!x0s`jdUh0pzxGU@(7-2VzN5A7#r!j6P>Y;IQ>`zr<(I<~^+Q3F-NY z`0a`qf1MwbCIH@w@~6?IRo|=D^8vm~dC+ASCpu$IszN=^7^PiRnNel*K#JiWf>y&u zddnZaGNm9<{ce972o7blR^h6TJAR#%0)HC<|JhrPTXk1PH{A)p19mou-KOj70s6lf z{Qd?3$p62HT&mvRO!}9|x*z}m%wHnwIht5I(bN5N{l5hMKbW=uCG@JqiN6F!{D;6n zM?MEdJi+pbwup*ukiQTxFC`3-_>AQ$o^I-)!H7sr=ID6wcf3q%x-@U3XId}|Tw4xB zQk+6mxr%MH?pxnH?s_#y>YzQ%>JPo5ymfT+s&(rjBx4OreT*fBh7;U`zZAkKxLFXH zPv%N8hrvLSV)D`O4-qgmEOlX{Sp8M0~PG>hao`L zAj~#3U=2nuKO7%RRgMXbp;2&Rglp=eL39c7Xw7?vO3Lkom0=!Hn!LrN4T`MEm*ygF z;Udjy(LFqj{XIptkKq`0ILWt$>nZzVOBWf+ zEm$?53l40XAbjvtO*!}9vWop`MvD*?09fz`0FeK_;cDSzVMlLlXXIk@w@Cg|9WQmZ z><)+H{rGmjLIpk;7=fjj3+;r~`7`31BL1L7KMi;kntHNKI*vk(&DDIMk{~?0dPv

icn+`)%>uju0onqB$v?){>{3cG+BN!S(I# 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 CblztG literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Inner Graph 1.vsdx b/pic/UML/ENG/Inner Graph 1.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..2e7dfa3ab8fd96837406247fba6998248637ecdb GIT binary patch literal 26727 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 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Inner Graph 2.vsdx b/pic/UML/ENG/Inner Graph 2.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..2121ea172f48a8f8fb1a37b0cea4438a7a907f49 GIT binary patch literal 28214 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 PxG*yaFffXCf4uvDnY#h5 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Inner Graph 3.vsdx b/pic/UML/ENG/Inner Graph 3.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..be8433b8ec1938b8c633286d25ae114a6ce6def8 GIT binary patch literal 25193 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

@MTVG#OOXk=92=hY>hL8;@uacdNw^Fzr z1cW4tPp(*T)BL)qCTpDl)4}WYa(a7sA7A!Oqs6^tKI^e$JIETvT-eRR+nt+j)-~!J zEl1`I0lOfp{JlLOfPNls^G)RaN|y}{S4sQg#n;nG?H8;CApC9U;r4a$`Sxc~eHlo8 zS7;P&R_|yoJnFl{ua_ku3$Z_X06=Nm#Qt6?cgavhXf_s@*xkT=cI38kGx-yZY0QNx zdoXp)q0DA|o_Ur$p-cUZ`#GR8chZN^3`OxsQ9|-fKY_K0ZM=c|&l6ml# z{ls%pXRI{e5Kx|=esr^Cv`_3G=^6)yBb;iQn{1Z{iWYEZCta!~JZ`luiU?UI5-{o( z8wcZCgk(2Mgwa6t2z8l$N+o<0rpgy~kZ|`byh6HIbvJk8%NoY^kUbvzd>s9Y`$xNh ztH6h`G;D}#bdbo=8F)7;al%`BhpLCh7LBQDZ+pHYphad^bCNC=Y3F$>qA4$U^4>u}BtP7vR#fY!1Vuz75%&kIa3i0#Zn@E;W$kSS!x>?SDPnt|dP7fvIzV1+81ldIR2r+cs17Dx zd}j|w1joUbtuDw7nzM|uE(i+F39{>|jjKyO*=%I*lKMT4z%~^5RoL_tt4Jg)&b%S7 zMk8JmBfBTZ)mMO#qle&)cZc6Dy%_3^lc%V(RMZ(Z(GVRNF{vh#7s4XhFw&vNLREJ( z%-Kg~ur>-*RDp%~`XDqO)1oH#-4oKT^TJY7qAWn@ODWSpKFf@miU-(;YqReEiffy@R|&~) zQgr@+Sa(J7hjragSIo3rMaVqxQREf7SZn?|Aa7^z$*MsXy>B*>H3DlE0dMx9Fys$~ zYn(RFZcoGxC!Ak8MhgoXXsUs1_!TcO1)=M2BYIXS3>B@`ho1qqiCKu6WlYZxmSybE z)g{NL4ZZ$xCliz<@(O9?qbB?e8s6cU1Y(C^RZBsILcT1vrYi>u=5DEiTGn~V0;Z0I zS=V_bGyg}m9Lml9@pqHGAXkUwcGNa(5KSVi4)$+{j!D^UrROe<>s&AfPhKd< z!SO2o~xVpRdX$6xw?6(sV*_7)?PmQgiC-YNC+5hgWI_U zs&Jc|O{}SnY^gA@m8o+z38<%@JDi$bSEvXJ0&`>7=A>954eRUVCd_TQptvohE1r-` zjIr%P&Co-(G3}mkX$b=;wW+af@LP!*sD<+(QmpclbqCerKtx>vKp{6l44Bt`33nJm zYCny#yRBhyh~Bl;^@yC6M=Z4lP1p%H_o;yv6{I2<&Q>10iXsIpSV7-8hQHR5xJJAd z%P0633Xl#fZNPq8!_?Spj_&n}^-dIN!MJSWY*BtMIzjrlyKcFw-^ph~M9P9SieLe> z{HUMFYvXL1!p`}?yas!rc^ZkTNlBq!U~TG!qxz8B>7Fn|_gp_+iO=iR4^fhVhP@Im%DhT*rO-DRM&xtsx4N z@2w&-5Kw_Hg&Vlwd>A6M-oM2e>NB>COO_L`Y8N7hfKp_`#&P*O?| z7`jAqKpI3klp5*o2G2b2bA0jP^_+j;oc+tpn$Nz!pEYalz4l&f?(3?!dobi`3gKpR zPJakiVf}_i9d9R#y1398LR~fmGv6r5ZPd-*(Y0z#Rn!*qd$UC0`todSA;b8&YdO&> zej|bHTCAR9Mhdpx!{>Kh8gu}N+^!8}Me1oKe))M*=rc80nI2A2?J3FUhcSeSs_cqs zFwF9ieWn#HPy&$Su%ZY{7m2#RjmDUKfs41E6SZ;_y9 zw|7=Pjur*6eem`07iBg}rDmxroBPaG`-P63?>R5a)Qlpp9Jf4!c)VmYyc3TeDupgN zF;lvAEtgB?(WS_T1s{Hjv|F9hn4*6^PK!f+sTSN^OOH!Mb-vzM@`%Tgw4Dy`=iJ3K zn%p=JfOK=Syn0Oo6$@^x@Uz)nt&SX!Hrz#T?K2O5{}UF zfqv{7$jmf~Fl?PAB4%b+=D??TdF#*UjL9@A;Zbwhi$z}f z?5qq5)Fg#KUXcHOOTjmKYU%;HSyaOIFXr?b_}(};?Nl*qM&a4} z{3Ovr%z{yy!Ringoj&ZY?^R&ku`XnhmvBigR96A(J!Wrh&eNA2IMu<|S$12gV)k1` zvh${olyz$UmxLG<$B2c7FQY>fqyIj5RpGgj2K2;b)|+KJbv zof8wm0e8X+%U&w%3vKp^McG*8(5B|c5)n6% zM2+s&5^{YkIdC|vqPJ@L^6~bu_^d=p1C8`lQX7panxLP1#3s)%k?MG(CB1-hPBdKt!N$R0H03enNvAt473ve14(rxd-%L7C zoR-x~(W>6a<~^C66@hk@T25!Bn=M*s59*0Q>o}}zj2fb;xepwax}}gAQK=_l4+7#a z=sKQ<0PyM_Ts|chuD0+W_rR&Hj^)PJz$oNGe@e#wTx;O;YCmH8WNM4|S$>9L!I}ILBtm5VPs; zxElJ^Ph0yiD-2l0W0X7)WG~lWC4EMCn35er4g>tQqzi z-VskPnuUJ&lB3I%YMT8NtZEoCVk@TL#4n4lso6zL>6O0a-96V@l7*X~ylj>_D8BgSZo>^s z^b}Qc=+geY#(iaGSgl-8hadg~PLlkPD zcc-x5Sh-dT9p@Aw!)8Mbtr?RB>QBL(9Ow~m`+5yWt%t@9^=mauUge4OG26UiUHQ;4 zD+gHHsSO;b6pncmV|>9>v-nAnE4f2P8^QodhI~0xkq7muCevn zJ@2LS2NBt7WP;lgx&n&2#i)rcUAUPOPO_sddgtWM-1n?PC64no09|_OL(R17^Pt_Z z$^_WuBPXke>P&(zlO&9U4VoH-MPTBw1Qm{+F313Sxt2;(YK&%YOcj69czJ%VXGrm# z!~>PHWTLYjiwXGMGmWrd1II29h~lbeZMDfj54^!XSW1!CS6$c2XFFNvG5fycowYG? zDywcS+(v{N(4k7@`bHg~Rj4pn*c{v{#+_56I<`DpIRipXN=(RxQh-q9lS|GqLb!tG z>J32AgReQn&~TNuVW-QdlJ2nd#YFGf62`9hnbgcYte_R-IqQWo=k^M9kZqAxF5%p& zQ6?i!?km^`onb40Z%YhEr0vI{msi>VgOq#M#A#*983|f(%V6@!LDw=A?TnUOTqE*w zZ@YPFmBzG``FgElIo8|s4EQOvg@S$eJ=E3m@L8JKPMOrfo^Abt&6pvjrCwv0INZd3 zi(2&|dQST!U7zkXwsWFJcX`3*i*YNB1WJ9F zKIu_z%w$~R@Ffku!wuzi-QS_m1Ya1$VtDW47GG5~i;dS9jmVU0qh6RcRnrQ!tsp+@ zskn}d*`^L+X8}!hNP`Yx+>5_hF20~wrAocXj~!`t@P?yF&112W2BbNM zC7j`om1&Ayu>bLI&hlMQF*BlCQeP1Xi5PJPLOrAW+QHG8-Nn+?&cxo>%9hRC&SF!) zMd|xX!px;GV!{Yz{}&;(S^O$ltSXP5CeX&m++kEL3U-877bGe&xC{(EA=r{Rr4r|6 zTwP_!Ahg0N6^=+~yX%saq|UH%(K%~iboIki#89YDes|mBayIRxX^`?_z(Y+<_A0tW zEi<=rW(sza_(}DrJoA`G#aXT@&(U>_>JQ5@V-R@D-InDYb)8`L=uiIg?jZNxKEI8k zGh@jnwX#t?TL;I@`g64_=(TD~q1b3y_NLP5^`|K{@6|pm^7HVL?CTAT!a?D94G}p}w z(HQm8&-_Wk>&!g*3Sy1r4NBOf{XV)x=6@$iE$)8D=G zlVv6&BU4jTvr>H*6B}C34c%XlM~Q zYRPRRJodT>DXLXH{9ZSw06qhDBn)#Gd;x@>q&nBq@*kBxaM*z(dbsF+RR9kJ#ww z8eP_MI>v*811ArocOoHdL+qzv?D%53q+BS<{*kapwTd~YEdjE?A=_a;;ix&(PDc%7SN@kbvM-O&C7rv-H*|oK^<4IG9n#M3k92OSz5|8D-T z;+L%DKkJTYkk1cpQx$&b>12l|T@6F{?b<@QQ4W&QIB@(r zYtf1tJwkN5AdWoagf-}LWqw{9rTGOZqgX>jL)M2E(jf+V!foOZI*T(##@#l1RZ}<@N&DT3TuDwtPFKa>p9No(aT?iEwVBNlhn{? z3JBYL!X79I5K7oL-NPn_>w}Zu=`S$rPwlIDggd($o%Ikkw?SCNLc;j9?!`i=8rNRC zxQFRs5Yg#wv~9tZ;_-QoeB zjJ#1hsxDu@DdAU^R-Wu6-0S3ne}H;+Je|O^%{{qK1&aGB!I!jkEC^7!PlHwT8j{mA zKG5%^USGhY;x-`5m^5kKKv+XttEZ{Dk^=h{vtlw>i1EW`TfVu67-vb@o!LyGx-#VZ z(G%hv;nA;zgig<;hryOcxyMiyyP6d1mojRjFN;2S=Re(;(w-w`L_wjbJF-EQz>Vf+MC-?(+;ozB;Nahh(SeMu;E3Z=xS44XPXS0i ztEHIX^6HmUO(}>shYH-!+vfl@Qv@e=w@*f1S|MGfH@2t}PI9=lPac?%m{Pr6201kf zsh2NcGki%I^GZ&z$&O1KolGOQ29NSJSugf8uQ1KBGyP{l`Kg38smcwD! zOozf!u_n~2m_;!iOQ=V{O3L9OlGf@zxeaaUEAAz!2Bx%AgI3bfQ19giFcX6uaap=Q z3eJFyVkXlkjt6IWsn8y^S#|mLRxL^MQVO~+V%l&Qo0hoYkC*lZ0*9KF*4lpT?;XK2 z{9ripcCd@8aWSp%bQ59}1nHtU_p>{*t_TN!9kSpIx|$;hvgt;<9HB3ZeOOwRZ}o}h zcZ}@FZK^N;$VU^yQSZ^H zm!=m52KVCm-zQohynpXHuwrJCL;dmY+CbybH$ElPTIZzqv)EBYvgdhoTljcpc_!2h zq5{}E?%VeV1=&n9nJ`3Cf}RM$j%;krlF)wK(Z+j{choZ~Ad)pIrPlp%i-t8`CaLFR z`>^~6Sps}mDLB*YF-6nZhMgM!>&K?yLZ67~AaJAQYb|a~m4(5W_IjyyWGw0tM)&*A zrdu0y3uxfDT6o6*vm}j(gHDtxBbP+8d-zJm;b4h2HLNIJoZ5ShFKs@DR3N9-!?0-z zqJSN0{Wg&vu^&U)!jvq&qq9+*Gj(`Ld$a`aO&L4Wxvm7%9G`ZaiN5hhK_h_rI(*xo`9<+eBTc6mr9DA4Uz-vD5 z+-V0e*z+#s8CU35%I$SYCr$Kxc4Q!tc?gH*<5_uYbH1IrTxkn3Ycaa6*@3fhr?S7IzI77nOV}vnJ#U?;b+SUS3!J5`)G$_7?VS;2H$=@X6p-? z46lb0tD>hm(#7}-Qe{h8dVj~uUuC3G(_KoXFwnX3)H7`CbyF;C+*w1O_;Xb&F2b(G z36a_Mh|ESa+c&ulO*F7+d-gD7=iUY0lam^&^K4c-fZbi=2UCLV zZnQNDJYVUa$jq2+wy>`gk~T~?_Fcd{zXb3N?Pl%h-WdjB|Q&@$gPdP8_KzhG*05oG56_A7Ywy*(}zq595GJ2P&BZ(y>!j z#B+t^R&#j-GG+!XgJ1pN8C<^KT5J_qmsydv_)RO13cb zYF7u~`_*7>2lVu#z>Lrca37ypqE~H^XGJ0BMObXBscTj1HEGHNa9QGb9!&Ox;EtUS zWAj=odCpgc+mqbH>yrJ7{~ydsZli9ydEB7f5Y`TV zcja$=>z}+mZqshNWZckf5jHA+)BbnQjN8Q9MiVzg5an&+Z?+S+F}H=gH<;H?eqnCO zcyA+at0iv`;!ppHxEZM%?c{CRZO!2g?Iq(c+OLuN`}JR}+nC#Oq#KM2>z^_I5+~ip z+!iC;V467ojQN)|;Wp-W71a$!PUIKnW|aTLT`-XQW2JBa^YNBm>=@OC$DFN$v% zsOrDE@!JylcKAORFE_zRNU55?b>Y94GPk4u`E2)lbiK}R(Z8PbZioN#2Ksw=qW56vPJlFy*aZ-I^;he^0GUx80{{R3 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Inner Graph 5.vsdx b/pic/UML/ENG/Inner Graph 5.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..3f9123dd5a101df334d3d25ed3d6e6b7ab6afd7a GIT binary patch literal 36979 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 Y%A242vS`WIG{{%B8!Cx#{M_ohFJRBijsO4v literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Inner Graph 6.vsdx b/pic/UML/ENG/Inner Graph 6.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..49ac1c140bcb9a497c1056734e92a399ef2179c9 GIT binary patch literal 28162 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 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Outer Graph 1.vsdx b/pic/UML/ENG/Outer Graph 1.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..1b39ca33eff59194c5041742d52622fb960b632e GIT binary patch literal 25756 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 GZ~p=q;u6*X literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Outer Graph 2.vsdx b/pic/UML/ENG/Outer Graph 2.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..42a61028ee9c3bdc182cd986bcc424bea07cb034 GIT binary patch literal 23097 zcmeFY^OGpewk_JWZLPL#+jg(EZQHhOuC{I4wr%sSz0Z3)&WrQi_Yd4#6;V+YS-;Ft zIp)k9bCkRkFbE0&7ytwS001FCVu>-bGavwfIVb=CG5`dSmXNKDld+AHuClwGv7oT;)I!Sa$@QgTv*C;1_&QZ|&GZhW@277`2F5ZhMz zM_d!ko*lkhaPM$HfXtC9J7E@fm{Nz4nBhrY^zKSpcO4`0eFbpPZodJon$fo!_h&$m zqA}Rdj=dsUbXyR)ukYV(eKw0zT@nuqA;<7qrnVT^~TNoMu;{rVJIKQbh-+p13C{;6|V+ zNzSmjVH6*advShf0CwQt(QCX+Bc2nqVGVdi{|=w?6=%;X@iPpc!FflsYxARfuKXrm zHFn4XH)qpm<{IU&!I@5Pq1EH$`79s_CA=w2nhh2rx>XRsFH!onL1hqj4{EJV1?XKw zu!W0cRNbr|Z1$9U^ukOwsNty~%lmht{rms}$p3%XTB_dPMDmxdI=}z`(0|#g>tJl< zNJsmx>;Glx|H0J!Z=qKvPW+3dA}`{ffk)m4MchI1i8cs|t`NcS7?%Y)L;F7ThrQSvoL&FKK!ruyEE) zqRHG=i?F6o+hiw>jllvypdfAsmd{-G1Ll<46u!z)CkUj z?k#yAkV&~6FfvRdN|U!3G=Y)T`O=)fnmI|bnsp8jsv?oG<9+#dze5E+=^22emGZ5kLgsUR**wxd&YRe$pRE-{`6*)U7Vj^|2@ws9bQIkO$07v2gC7$J+H1MOSh2r$gw{5u5>)(WqH?aT6{ha zbAQZV+Th~^m^CMb)0*>?(=MAz%{hPEoLMksh9;#{O}@!v63h~+qYBn6nA2Z>)p>-1 zs(EJH*g7A->1!o_u{TSKIU)k>NTAGgGHZnIZ$ydcP|=@RRSy&0D#o#(19O@){9o?nZH z_a>mn!>#jrfYT1Af(H&Aul8bO>bmsW#Rb#lF0i$^s-A$z$MbY11bVi|G#?&{wz~6H z)eo+wiM566A~SpY*~PK}^n5PYgJBf1XxpTwquYOmwu@epU%{h_HbB$z*7mt&ixa9- zi@)ZjT`{Rs2SI>x%8t?x`)iI9Q(R;cgez7PY1Jm1_)8=~v>|HNT59cO-PZS|w8i)R zrsn&FjTD5Gnp{U0MBu`!rm7JD6=N8^bl9=T@COq>`B)NQ8XA0;qU=)vYEcu^}vWg5L_BP z-m!{kd*OmCjb>#BJ8d4etQcLT647Y!B5xanaQ2vE6h@BIA{#QG6#Sq&9>&2Th%xj; z38MK_mkp^fxjzVO{y&kyahB$wR_ymcfD0Va2H}jN`DNDx>g4rv#-Q%((K;K>SrHN* z$3uAutXEK_agh+%>5)zd#kDT2WiujK@3VPdy*Z zcUG|nW_x9IH=u>+a&HDgr^sr)dtf0Q;JWwZF(&o%l;zcZ87LM)CvD=rdqzNl^i)(a z(!)eBfIudqpqYi_l|~LoF+TuY?6V(4sqzURS)^oQ&gZkQj0 z8C5uSxnQUwM~A#&82-6aBYCbioHkcw;x5^Gig=I=-FKojRz#X@p8;R}&^p?~21Ewz z^7Ppti6@-TwzeYOZp|^z>v~Z6Ce%Q&(^hHHGWoL&o$R$c`(q-_e)qf*V0l#oW{8f0 zIbx;X*`rYwCbj%4odA>3Oo%&-*4(jrl)}g^Lp~r6lbOjvF|6! zzuT(3h^}?T?$pPG%2$&j5#Tu;E)uAtWT20SdZoIoaJG2h*b886HurEJ&vr>q!F}>^ zSx!^MOy^ov0fy9Tez8c;>~fzNURYxCq4wcC%li_?H$J@2ed3`oHt0|sEq0*arKfEf zwM&}Q)u8!@fxB5rCChZ0Tn6VZ&#JsZm!&a*Dx0G}k>GusEo~^*%TblrUn0OwS2~Q> z%T`cdAW5P*BgS^ENt@^9r+BLe8M5nC%xSIVO|i!rB1I5q`jDa?3&HpVTCI)|?^iLN zR*uT0rBlkpw}o1wI@T*-4Wz zXqzq21)e&CV#auvJG8WFh8Gy0oYn*6>7p(Hqsm$GX-pn>0)XsR6PN;q&@IdafdXWG zMOm{$eR^U3de35r+p-(AUU0|@dGKpMVxbY?sr95++E=nC1IqLuL0Ubq)2cHczwnca zmYH~wVXt2s^uYrE7?WVvrDrnyp}ikb-xHwjRGS>8LY-s4P^loAfE~=@`rXPxkG~Buwk&CC>e zAZ_AgcsL2&td%{z{JhM0r0wUptg`D}3*Sp4ss7@^>Y;`G{wS_t=``H|RfQG)Gc{y0 zO9nBMzS3_mB0uue33fFR@YArVft9PK5WR!{gCi^DMp|DA4pniw5-*c%F-eD_KHDXk zS8=xFryn)0c`sA>7zK-|@jF=?1*YV%To0jnpa3L6wesB4aCq#bA~yPjT(f`o$PsJ@ z{6eL6qKVk3P+Ub>V@0}WFFslq^vE2J1fURN^;}3_;;}7^?~bX(pCOa3?*TOtIU?Vc zPuuT^Mhy?g?MnX2C5lFMU{+}b08El`7#5Q|t-i^|M=yxkFW<>j2kXPuV%6VG#%}Gd z2NEUrRmSeKPvPbFP&}TND~_ijj-L8~^;aIimCI$dm6da|3+swUrWV)5aNYsEibIi~ zC{8)VT68=O+0i)&1->fn7BpY>IEe@>bvDfm(kZGP!;ySPH*h1nUh(b+Zz*S|KgZe; zVvP@?2OMp2|<540pe4GwC%hSK~@l_Q%Aqg6YdRz|B8eS%)H&lY}lxfS1ckK5e8pMHD zwX+<-$Wb#0=$0|d8Q`b_{A4%dgffgQJNtxuQpXF7P)R*k5O4?!andOx+#JJ?(YJMq z(+ziG#tlfENpU4NpDyN)e=)U7F2=GGHiNuyd6YoY<$LYI)W?>Hq7JF?%R)KbjiaZN+y0<7)@Yk99m1#DW$$k_>656HqF3>^em} zyS66i5A>-2uhaqhLs^;WVSzUVN^pZRR{W?FKWDm-4%1r>zO}9hor&8txbTg zb@|D$pdyog z?-I?xXnS2s2szCx!#0+_ZCNt7@v_iLEHU7LP4QdK^HFX#7@LO)eUDbhl);5N=e12k zdJZx+K~}~F<4vTq_6X+!wKZdplD2eBKpz`&3*fXFkw#q>MKN=ggA7=#b>69SQ6r|D zA|4qJsJ(gxnO@;-lUoPn{Eme~0rB+!;=x*m-?)ewy%Q-WfsDq64Fd7~U9$jE1}N#~ zs@?E;f5My*`NNB`0VEY^n~v)uLIC|E3v)oh$~7v97Q_!BbF_^0+R&2tTQ1O&AL? zO4=rY%ho0d#*dkx879rp1g6Zv^fH!)E9tGYO3Dh*kDHJMCNCwW>!SM+LjffZLYO)* zsabj;+pL;Z*8*!((bLh~BJ9%x;*9l?@S}UVok3DT+F!8OpUht7vahs^Uoa1ZrODd* z)}T#!H)Bh3+*K(xLU#0(Zn(^vF&zEY1s4?=_}Iv8;tDhPUXxRIW9L%~s4CV1Unh32_~DoMMrNLC!1yk`#8-5-O3litm88ZfbnA~< zcJ@&WXl{t zFb^ZrebcaYFUZ^GiGHXk~E9!FM`L%VO*7d^_6D0 ztG%r2ejTg%ejU~P+z+La7F9OVgNDub(-kyY?y63svo~Q$2_?RGQUct2kmV?;8&~Fm zI2M2FSqAu?0TB<8y|r|)NP06TncH$>ja#>X##nrxA|Juz_oMmt@Xm<|VG5#bhv)xx z;p=#@Fk#Z^FVmAuje>6XSYrh#UM~r-H~$8Z4)W46Nk~qQ;f$RuGCt_P=dMpk(LiG) zM{8Ekew>_5KQsj!A{Ag_4?DXb zADe}ll#DQ;FFrH_(+{4Y$7oYY8=HrTkjpUfOVFlBpO<$+&g&FL1;~~*_iHthOl3Z* z6h*I2T0ai(_qQO`X!lcn#{~{bTLarSc8@MTl*+-?T!Bau(|I|Is3m@LS)v9k8;*4D zF7u}$F>S{jx8bHvV8+Zd5>I5IVqi8;1Y{h`1QDSfc$fJFwdGRo0+a5)`ij?tRmup- zM7)3W5e3I)6m~i_=U;!Bt!RI=sBxC@W+6RDs3byhA18ov7YyBU-u4R-GsH!h2si;( z$8pU{lw1`S4^oKw`W|aP67Klsv10kanD(OgPqOy1M4R*ukTc)s&dJY13*XOnQK~mQ zdwSCVj1S@tFl_Nx^Bdl1+;2V}ZZ5BG-*=&bIde`TtiH1+ZEL{P(tuRb*a1rApy-@= z1=Z`fL`R2TMiW6G$xO-f7)V)dHmqbOlR1CZtYrs)t3y8PysX$8nWLhc)jM@jw@emI%X%ZOW3rCNLc8pB>O@ zp~1y4n6O(l=!}LUrm8h4s4QDG7^o86+6<&7>9UzR2Is4xS#IF8OT@RUtdnRLyt=3v z-6zCIea=yDNiuASfmc}jWf7|B6lJkYoHUM3Xq)QGiHP%C^9fqP5{VB;B>T$QXXtFy zp;E7mCC_gC`)8AYZ+uF@RONrpVQY0NXWfDCh1|L#>;d$oe z5Dh)n>?&D)ReXzS8qdTRj#In-*H;5*tB*ZXa5rR zBM}q&2n-`Az2rja5fco;%X?++KLd=2#b+Jkd4!k$j1HywJ{~~xz0i;B`Kle-aZlU# zZJ?93yN;h0xx%%vj^%1-D()QE_T5b1F}>ltp1f&z!FN4=S^I$ZF|C%w2P6|m>rrSO zoWy{|8n|1b`+0rV{rTcb5}aqh3BN<}F3ca70+raPo0LLr3Cv!DpkX?F3k?7KrEM~Q zPH zX&=%&Dyw?Hk%CV!cJ89K6~M4T4e(ord*uUGM!vDwDnl?yc@xak5p8=K&uR)~Sp@lH z-eEHkZC+*_rRxWM&rTuGZ?%OYhyr z>YG0x3QSIi95l|?g{YS?bL+JYUA4R9U4`%4vA+WSKdAJC2A8ILe|5xvwajq;qbL5CR{!5s#eeJe zMe%(W1N1Nh$)zc77seJs1) zq7pgZ`u!6^s?7!7jK+eQ&0be~___l2EfScJNow}?Fg609^N?hc>tWKOc{2JADy(&DHyQJE>6ezx$+cc!EPTfdzK3G^&i zhZP5v;sAiI)=5xi2st<#_@yzumgw2A(xGo{kIs3GQ@q&vYZM)%9{9{%bCtV0#?gEo zreU*YY*}cZmv#U4DgI{%BX%JDvh^<}(0@k>{)3I3zNxVz-G3qU@B4p=uK$MT_sk4b zKRpcCZO1NG(xx^WJW;(1o4(o{IJx#^#07o^(fjjo<^zVHk8Zb*Td)XsU7VbPz)B+l z{W|m8DavN`$rd7r3Nl$kQ5e*=IQ{8WNzbkUCH~wc6Qn8;MVjRl8O7K%1`G>@;o%fd zvL0pZ(3sWb0DIC$GtcO~rJqi^K^97q{W<^do%Fa_h@%2!$K0XqN1uHP!N_*C-o86Mmf+_LYLXys{nR~?({!@z*8ttQ zY`QiKRz?MwNZ;^Wu*ATN-8Z}6zCpiP3WoTAB#d{-OL($8kY$>bgqUzM zlly>*G>VZ!^janngIrovS9*AD)rH*T59X|O+Bu`eXlflOOQpo5oYjq03{FjP{oKLU z7$A`KISop&Xg)PeA{ix?kE50ZP4CL^G4Am3OjzcKGv7br;A21@^9lk0z=sR~fcZag z_-_bYs%hJ3JM9Gu1k&J?3N8bUkZ_DlBy`Z%sHRC zFqvx>S1+;BbexuKtLzc+nLr+zUh<3(*AY(5v#JzTfv;t~yt?N;E-gLb)k4tHR7mkZ#4xA$E)*V zv)f?SZ{u0BZV3-QvIeTGFDc8|WD5Tk(oOZ9)pDT^?zU0A!(<+3_cfhVaH#o(=RzJw zK2aZQohXp>WQ~B^fgBpD(4FKf+ypG zciH2{`gVr*`sMxNxZCu*RDjpN79hrI-d-J^J1aw?%ElgJJh=28IcK$u5K~6fd?Zu107WOFOE(RupG5 zPY4?ipjy!CV{m=Y^|Vf96nnKf*pm7H_Y={4u9|#vcF2e*b&_0?G*g1Yf-^BdWNC3o zQzq#E?@yXj`{O2Uw2fu$whegN_93sNph`nUh1r;~jFKWI4eHe{h<9XRal@Y1Yl`^+ zMN`7(3qz8ZBLG+FU4~7qnfm(xTw%VLyPTMEHtiZw<6hc!Cl~g3hUM0FZw~B-F_fN? z{BK>|NEfFd>L;E|^;+7QUe-TsdV#ixnX`Ldxzrn_q2nj|6DCr)9NC4RqJ?@8IRg>q z3M(gv7AW*nBVcd^6p;d0+6x2t`+L1lT6XHaL{`hoDWrwDFS?uBoETRzt~s>0-%poz z;FUE!Sy9&vKIw9tS`We88<}>ugh3Gy$qGySD^z*}$_@(P`B1+{_1H`ZowBz8!1Z)E z%Q&kN$)wzWfR7FDTkq|~YlCbGC4?$*Xu*tH^3dko3m@@$JgQ8>F!W8xH`LVZSHO|D0z(=SMUGGmO2biO$T$f_B(sd9iUS3O7GqqJ^sz&RNghrG zc@2TsJOyge*4^HxY@8p0R3|bq)BX|PFY)1*A9lBIU}R!gt2#QolCqUa!e@PSt5)EA zk3@<)uH157~nU*I$>Vy*Iicch43h$ z5FG!sOwya|N<-TYXe!%-BVYYK?VMBY6@+i!HZG}UhAq+)qqnc-O_P4gF&jN0jv*7y zORGVS+y}TrwM1tuE{7Q7twto2?|&?o1UY;u8GjcMUVqIwsQ*cq|5YsiQzo;NrEE6n zQ8v*}aT^aPktj4$tkmHYvCUx*m4qcSs4?Hxh$Q1FMKtmchX$zH^f8i9aV*%7Ld#8?Py^eJ!IYjD?t6k716f;qSk!2y5Ww6>R|K4o zCtGaGM;SMh^P33;bmRcZHrZ<&RaR1K^-!9FK~kbB=cV|CEEh9jl8rvvi$b?b%3FW> zS*1X}e;sLcwVKpQGL6ePH(+5B%CkY9x7s7b>0mh7M+IgtY=8vQ_W7({1$X&@u-gzX z;P7*iN%L2%u$0I1nPmNFYxj5g{DuYpwY$l&k>)v4!pW9`gwo-|79q|C^LHz=3*p`| z%GP__)+{f$X)|*ZPY^cHT5Vyt;MLBVJ4HFmh8CqQXkZWpuDvsoJ$l0(-Q9E=c(Ui5 z!`dE#1>Qx_&mK_-N2Ru^ucUE6SAn|*H>jg4DYM=wcy0hV5g`d3i^>q6-Qd+~;!`JvEmcZ8hNpFQ;lyM&H-efXr@3}*|)YxvR z#4zX3lFY|QIwiDoP;P7Q`*OGJTBiFj6ryjs@=XJxrI`|s(toJ$VP0&T*`ci5_woiHy%AoGUfo3Iqs>@3kH+>;gVAcwM51v*kIef_j?VU=>sbA3iz_$K^m|vs zE2}%hW$s7=zJKcWHg)FAL5H!!llUj=<77Gz zZw4fSZ_eaN7ZX7eE$P?xg#L~*P(&^IEJ9nFDDO3VqkKb)UZc!wDBF?i%Z!RD1?U)L!I5xWM-JfA_&sJ+$FK{KC)}SETr}7hU8P)YPJFRqb zpQUua&<&FSPD*H>qEX;QulPw-jX&gOLqm7_q+<&zooOV+L|-?2Ki_XPKQ!pxNv5{f zMR0RAoQuHPJUmw~aG~C5eFciVW!U!;D2URX5LQd?^YCX&=OI)?4t9s3cn-hV_{kxF z^*~8EJnDQI*8hBAM9bopEBWRYt*}wa9y2&_M+rqC+ItHk!16C0J_c;|?OVLRzKl7y zr&&13)@vB^jtVGR12c%+Z=o#IvhhSb6k0joUvt6F&;blK=(W`J?NUq zB-Y?K%oK!AYp^GMbuAfD`V>Eqs?}WWXyz@rnno)LsM<;+t9%fK%6S}7DtH()Qnw>k z33=m^+j7kQmAzlIAxw4`O3Wu?qf62zudMQ*XFB5U;jR4%)&a@+Q98Ewy8n85x?6y> z-lxS*Ng7&;+3Gw53yh4bGqR(ugWscz`I!6;QaC$ez`#<4T(kIu8mw?gIJ2VD24V}W zIShyDGI+d(^LtR_Ifh41tk1n!dJSO69%4>vAzn%$ty!)bCL@Zsw;X09Ej+F7Lwe$F z9wJ&A*3aM6E(CIW7bQ`;+s{$cfjz_Sk3yO!=FE;Cow22&O697aKu44z!Iw(aCxRo>B{veyiX69@G2jjE8a94;WlJegUJd z;rPPLQ9#qHX1dPVG(>UTRS1K3L08RL71eq};d^(E^}pqc^+LSCP!kgj7Vo;sJ;MxE zV7n09K=m0rZ1k_l$7~W+zVmme+zr|pLl&4lGozU9S|1FE;rRiH8Y2R*plq5o?q?}u zrXq3;^3RzO-lGyYHh5SiHI;t#gW6h!#k)apTz-siQ^ml15E2cN*a0MlfyDQ*ODYU# zDXt6f14#*OyM%a%OxF&XQ#l4Q(`wP&q*kiLqC`fmWUd_CjN=q5tg;F zVmbx8zQo2RPo%<*6vs$F=wsa@cqHItx}3E!?K53-Wo5pxk};O~-fXN}EY7(Ar)5Wi z4_IzqX0*F3nFo$eI_!qc}!)*cecFE{?U1s&AlhMLzR8Ris8a zvtxEa@yFeZ3Mk5?Kw_;<6+pE>4L7wZPwgCqA{Z&{PybrK@-8FW@fb^?+E*QFmttr^ z*gX9pq3}dE70@x!K!IbCQswNQ?^fP9wAnwXKK(Y%{598bUG>xnLH!XcbXDe|I>|Ee zt6)g5g%oD#4!YwV=&^e=PG72RQ4SP#L`&AX2ldHUEWl?zb+rgDHH3KG*0S z^k6Oan1Y_#udtz~BJzn!ooe1m|vhi~TaPDCKih|Fo<`yYyebLkBodSA3!Up_P8|vO7Pr!t+FN7 z9V(Owe}kZAq~{EE!7m<#ScG6qW6aQpN7+1%qUnCT)bT%2-Qp={xya&l#e6F;yx zVw}fm7N;y_n^=o7WyUBg(-ACg@E2o#FE1A~dtyWhR~plx%H4^pQhF_1 z%m%z5X_H3&Sukn~8ZK>K#wn{hyMx(KJ|pCt*0o3;7}pg@>ovEcTeKVeMDPa0Qxcz?Pf%| z?K&uaGeIH00#}mE{8AY&W&AI=psry3nv#X7?=6YTPvvKVzMY$sz)ydm>6zcbd7<*-A*x!WXO8?0odn% zA__vwP>betmRtF4Y*|8#-FQh8m65{ax#!}Zizd29#42kdW}VQO?0HQxRzk3W!Vgj3 zn3KKf2A*QoN)Y~kxte^oqDE|;mZUO4|5+b!_QgN&6 z8uLioB*78;?WTE97T`N&86Q#mRJB0il4S<{Is>)azSk3@?O?}1R4^Efu>)<+Pk2QL z9L-o{9_kw>W!qhE{2H1y%!wUOIjF^wG;BMYB&~cp!#~l>5B<7;VFP*D5y%HYkJ0Y0 zK2u1jO!3RGv^6RpAMT?rPensAtoCkM%9;Wm^gCkIPIrmk+9K_BK}ZZHo+m%gv-)Bm zf)f|3VhxewJjjitL!^rr(}o#imNRChUzACP;sVQG7lQ>UjP2?!8qj9-xs|0~AGnLvP`V?>2qB{!M# zuHS0PHDMyPP=)2wOQlP=d07Z3g)ga$rq9{q6Zn6P~ z4tpKMTr(6Mo31&ICmcNlGa5sA!G*z@DCa1WO$zN|K@rf@*t2C~+x;G@9t*dHI< z(`t6;!O3y;2E=(K_N2q8PJ`&DuW1I{NY+#R=~|_GZW@_kZO;yPs+mkv1G%XWVZ7hR z+;K{$qcPSQvX^EHjST~5n9WtlT$Ld!@%Wi;>M0~tEi#YoY%MamrP+iV!_FBH4FMu- z-VIX&m^7G31jS=z@@F5wL4RIX&+_}rfqS9r$;X2IuiP}+Urgv5Ht>nyckw>@df~(Z z@Uw&oD1B_X0U7~>7ohSiA`;mWTmUC2RdRZ2V?Hz9XH7Ojnr;9Rl+_+_19p|Mb zgDTX+h$I_N)eCO{t+D`kwJcU1I=Ie4R%+FFh-G^TOq)XE_|XCqK&BW=mKa#HQv*kq zy13q5Uq4=ZPAjaEZHV+Ss%RuqZ!HQBDc%Aad}7>?7W)r$MQ0`Yh&S8PuI&_mbZmZW z_povFke8)U_wA7>(}N%|+J*(B)Mw}5-O{bfL1qKW-^>0MmYX3!rXqopnQ{(M7R?(& z&RLY~s5+nIl$_jmmSJ}Ai9Y{Uh{}j3HFhADlVNq5OHvt=mlk4GFHdwvNrwSPM@4)k ztq1|#H(b#lLo}<;lSn9!tS26?sJu8|tWXbSRzPPNVCF}6R)}9!>3GJ3IybWm3kWlX z*;`VgFB#9*a>?EX4k`BhSQ716H{aPXKV-LQ!VeC=gw)kqaw*@cTy|Lf1=7uhR6BL~ z@e4fDWc)b%5II|d*_DCWUrm@GqzNSY=QOC(qdc*Yth}+s@rt*9@rbPv`=}cif(GG? zIXuceETHlp9|(D1qx#y)y2a2Bn}K4X*G(%P_F8C)XFK943l)dEwBy$m3UT_6ye3|7 zc)GN;DQqwzC%<A>79I>{+}T`1I+wPs0ML$5$U2A8_;v zJHN578=Caz89HM+lAC(HeNuSVYkaTb+^tl#XzM0w8;) z%r>pb<%={8n#BPhaPYHHLIJqhNBn*8O2dFsd-~F9RU-|a6)^^rML-FLN^xgjoJqH@ zth`Jp{?mE_&f1W?B6F}&>zZ`SrpzkEt_(}-)aO5|EJLysJ$20~JF6}+2DvSL&=uH1 z2QfO$JXREQV`&co_pl+%)~_$_f~zDDCs|(3L5pt*ooq4_Y$O6q!UOZD8f?@{jd?J=C$xyTVzhaz4hG2XP0@yo?}LDmesuZ|qe%J_;zI^H0Pu~j?1Zn_3Zc`=;~cN#T6 zpZEJ~t|v1&eu*AmnYQXjCHxqtL{F9e}B2~8J^R*F5Cuo8sz^a zoz1U@sFsBoGk#|T?1CklppB5bRT$|8a5xAtHd`0As~y~pLs$@*X{d#ytJ^Q`+c?F zp@#nBW&iyMPrZt%P+3)1<9^Ke**>17tjO{9miSQPGjeYd;#`TQB z>65J;1e>l!BwM3bFX9J0B-`a7zdqH+n1ZAu$(}1ci%v-OF?TpTG-VFGtD_SFT4wIR z^>fu?%lm^o5zvyn5hYJ6XH_g3%=#xx6J;nG1NC#POi*Ee@CVTPZr-?}c>Hngz_od( zqsqd@x(bGZ`8tYVbdoPj!Qwag8KsoGT;eV~-Ou~6u5O^Uj@QS&gSAq|U3(NENw<5s z*iZ>aov6g|Wc&<%O+9@yv%Vmt$M+JxFN|1+blM;AQIY*mx6VK5q|=e;JDuNOf25iv zo!77KRofy6%su1Ki^kWEMt+G?$;6$^Hy79n9_s+Rr2dPO;M1q0Zkjv0&iF zYGVV-P^x;NHJc*L{Zh}c=*<&rR9*_wpkDF+U5pG9`Wh!Dg?iYHyGrKIb2$@#5aX)s z7=U-#gWhc`d(34HP+;SEhG7EdI$RxTqEBOnWlQMm*AIXNzks!R zdl#0&Oxel^5G&W2)a^Vl!jrxR2F?9)slV>Xm{tbxlaRWKvQBS!E2pqg%3N%Q^k*PS zlMD-jfIgl9qS-Z}Kp@h|mR7nsl3w9<%qd4!6LUi&CQzX!{SOMgVX+#;=;v8aha@1b zQ7fN5CQ{Tis)mxX2%)yLyp+{qQ3u$y#Cc`vi)JHBYNN=CN|oZ)_>P}HN6ql;PY#Yk zBQ-#EW`q$|JL#D!<>$2rbjdcz7S!z;U}Mom2sLJg!5IB4TizRt(}FlNSHQ8Pxd{#x zR6+rH2@D%VUNQ85*DesaiN(D%#IBh0=4|?92^)i+PS6M-pX-1w@n(<&J|9{J7H26U zvP>35CoOml7qIO#N=8?1-{~(OY0%-fZ;=+d?RO;LXG>=;zX^_T{}G$m*G6|b{db<5 zC0u;XvOss+9hV49C1m&;h-~J&LGLqF{CxRY-aW4AEKwRPv>Il&?5In~>#-JB{9UF* z4QW@DR6XiUb<9Ll;$NLZ1F$iuFvOz8tB-yY;HOdQ=S2n4U|3F3XoeE=zqt7gx4syO zx0Hz|hE2@fIwtNIX)`fH2ZGT%!28(uKb?LLx$2kkK+G?OzK(slB*+vKz4l0R*rhmp zsM=x_W9H!x9Nx5pyx>ARN%#k`KjRU?tZi%E4n)wSe)VqZhqNd@Zgd`=vY~(fcs(L3 z8s0mz8)>gNv;W@1ndi{j2g<^Jw?kk<&qi9(%%s7U=bRE3U=K$izFX zDJx2`q*H+2MS#q2lFC97Kj<$(+!$n0?Hz`JpGkEk+$M6+>XIp7?9VVV6c{OC~9lz^ECH(KYgzWTHxUh{W}NatHGUvpUMc4`-#{~;Ns6_5KCl=ib$Nn6#d1ho`cwZyMS zP7u-_omM#iMiuNAi1f`9+~ev1af)X)i*R58}=Frx{wDEGx-MlQhEOqMBmJ_QVL0%)yw49gb45;9jK$r`;8YLbuvfmb`0)TW(wmt znN#QE+!pl-^Kh@*kqPruUF~j*seV-Bbd^)&MzL+6es;Q^G4q>Fw%xk?oF{a@9Q}#m=Xu)mkdB#mM+>vm>CYt-aMCoy656B-(PNp zv5;1803TNsvYI|d!O;gpY9*s9OP>XlElZ!cH09MddeM{W8nNY!vCn_2ByAiVdd2JW zt>jQqCK+rciyk$Ppj`Atd$PkADZ$W}a_$;=Fj


Cht9|D(=bnG;1I>GR$e`Yx-> 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 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Outer Graph 3.vsdx b/pic/UML/ENG/Outer Graph 3.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..be8d82432ffd9755643d77f6c22620b99d84cee2 GIT binary patch literal 24143 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�LZl!r$%-jgO>8kY%jL9EetSI6ju57#$K#CFej7 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

&OIy^t^PkaU;3?D|w6Lo$-KI9rb7Ec&nCA9IJp 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 J=3lF1=?pHPw7a@2M zeSmhM(VQ_o_L8Mo3ZKROh{BAk@HyFNYIuW;I$fEbrRaf#war1k+`Q3r=SeMfu8FlJ}!G_V1=VbBLr&tp` zk1QY6o*C5Eol}x*eiXcS>B;O zer7kHr%4-`M}I2Yi!Cw8?7e&(|2H2F zt^tWD<-f01F$6#u-Q7C<_bj8@uO5qNAol2jSQYOh*zsqFd*ijJr7aWRq_gjlJ7>aqq?&SkXO(0&mpOT#mUy2&#`UvPKgUR&rC>d|Tm>(NeR&ET??9zD|=P}P0iM`5O zsy(-_kvS(vH^ z>eB3A`ZlzFw+uq|ZBMdqll#CPTeD-o%A zC^s^$!>O}XW%>5ec!eD4I|&)rx5g~|xht1n2QBTM>{$y+K~2nO4Ymq0UIryZjNNN& zEXJL<^@aY8gPbotQ=yOf?0IJpfKICER0D?bNu;9XsmQ#X6X}VKhK0aaQrDNyb~zd) zKh3^o-D|yI;x27#_M(yD%#HY`6-T48&0d>8Tot&KyayS#7RypjoO!T1eHtu3;>iz7 z5K4?cZK8t{gA`nz)Ev?-R6FnCVx*5yBpj77YDA;Tp-cJmwu$f8E2`LbH|L?h4U z1-cwK%@{)o-^4Bk*PpV7BwX;qiSEz(p>lg>#LOev=i2$Ymn`Er5fKH8PIv2Bp0dT4 z!OdT^ULo8*>=7oBz0k=b!mdYF78{hxg!DeWnh;Rp8D_`i%y&p zMJc2{KzZ~3K>fR{nvzB-P(GkJkrnKJ{;>aBu1ra!l=>bJJq0O=KM8*+F_ap(15Bpa z4-ADOjuJtsJ32tP0so2kqpCrPpxnxMfUuJNf%x(F{Q3IF#zsmEWexTKvvA?pm|u>D zvOIHu;n4hnp*-~m#Tv>%QC2w)X#86LR`Z}_Q0A`(j2MF-Bl;OWJuLg#TFUe%>mNZHrTO1izMswM&3`ukYaKM!qoMu%FgEftnVhg!SpNR$ EKf@)zvj6}9 literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Outer Graph 6.vsdx b/pic/UML/ENG/Outer Graph 6.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..2081360b96db0d90fe0ab60011aa945b3501dce2 GIT binary patch literal 22038 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 KbuZ&D-~I++5CsMR literal 0 HcmV?d00001 diff --git a/pic/内部图1.png b/pic/内部图1.png deleted file mode 100644 index 310a34b9c783f425dc1aa7e3629ed6743dc8301e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5496 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 R@T`vMq7E9Br{(zI-vH42{HXu{ diff --git a/pic/内部图3.png b/pic/内部图3.png deleted file mode 100644 index 85ecf030c24d896ddc896bd3d75d91ca841a5083..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6862 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 D?Yfe3 diff --git a/pic/内部图5.png b/pic/内部图5.png deleted file mode 100644 index 8f1d38075292c6738bc653cd61632aae8579c21a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13840 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 diff --git a/pic/内部图6.png b/pic/内部图6.png deleted file mode 100644 index 691d3f209da80f01b00c8b22fa2d8df8e0aca0d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5815 zcmeHLcTkgAyU!Aq08&&GkQOVbsDvd_11wlT2%uQ#5QGJ@M(KneA|Q(>>@Fe^3~>=b zKMNu*1Zkm!EJ|^M24ZLl(hNO-q>$VAOZ%H6>p^t4-N3h2m&+PT<) zK$W>0M1kJ|eT8sGuP6{mrB(WTLkoKl3<9YmPaL&76X!oOXoS)2U{e;3yu*L|@Z2%~ zAE{0^RJNVT4?MHwT+1reUfI-R@=Bny|9<|i z4OsKyHDL{AU}ol$AeJtN57h4N?k;}*gIh78_T@{bVb}NDVVG94VfcdgVCB4tX3FN? zbW?dH)^?bW0Ze(bX0;uv+7+d>8-_`vV2BjBBdT8x&$Ps&f2KTBmZ^%7>D>-s%7$=d z%j{%YP31co3dl6stCuzso~RMz6#gcVfl}wM0SSVOF|pA3wsBESrzmP8L9Q!-ipii% zQ#$K>-ZWVi&_Dh>HF&^36lr#6NHe8eR5j4@|jm`5IFZ&&1!x z);y^Hqo2GBqwK_@ZL@;*srG4abvqufRU_bB4)2V6(}uT#TDhRK;M}cMTV<-iCUckn z?0*tF%?WI1Ivg9<(tpH~i}mNP8WG*PC7Xi^UK-)iZytMeo|Eq^^z--k_wySZ7%1ic z1ZZkpypo1}SMND{YjjkX{~+!$&irw78O8g`dgaRoj#ebd8Ef0s-q*`5XJ} zfL**5<})|k)N`ND8Wyjt%&^FMUA1)?w2%m`zPT;X&87S|PNrndm}(UbM}gseauGG3 ze7FqZrBc%U0v;PV?f%tHURB~thBwCpB!a%)ayO`T!cAur-mH55r&o>St)=`A9!P_$ zdWZMw3g{z(e)ip_n2CHVNKR9nL{Tl*`YHu}fngY8D63!B(2%^qp}JlCE`lYPXCFD# z1?<-u|I(=DW^N|ccOx`dRbcw9L@yM>H?q72hiYg!%FRkQYv^s8n?qMxarH}t&pHawz<4z z_Sm_%wgUnCAga6m+WroERLh#B3*$E&Ykys2a#H1|eTWj69B zRRxm42QWYBoNF%gT3UBUW2N&TpMw4}A50g1+q9D@U=M0`^ejQmL&YbEp4BpP{vmFp zv2S0EB~8#v{yEK^61m8L>H%Ht(B1+?0c19j z*nO@z$FJ5Gs*OcpxSC(pW#DV;>+ejiYm7Oxx!hsMoz~85iz(^Go6p$($gxbzg!Ew5 zg`qj|XJ|{a#4iVesR)iL1&(1(`0tBXh-mdb$bGc{r^Hcut&t>(!yqK-<8oArB*R^! z5AMWPKhMgHZhMjirhRd*U>UWiCb192jJ6KA_epUHsd(&-+FlJ_+--d%R^|F*$WM#jDW%^36k-Mh2vK@I&n77WJZP+lBErBdaQKC*J2 z*Z-T&v?*+Es3B3vtP1TBFXZA%J6JVPnXFRciX? zH@H~7)x&?IUd5t_qJP%UnCKxjB`oiESs$<>QfKBFxY0jUu~@9Cs;YU5E|wH%MN}Z# z0o!4Mj@+1nRcLB1J&^}YsIwT{iz|4%@QEfP1)QKn5AETJJ-15-=n(EE6?6)N@Dxxs zGamH{+fi?;F0b^AK!oTwIghVZIs)sOM!@XWrGAl0;ZU5q;2~(X6j=;b8?hhuwMg$fH6J2n_zuF$^k|T7g^R&NT{WZ6$m+0V7Aa zg%H-rlxY7TR2Q2aTWv4z*o|kO@o!9GF4_h+8nCbOGHpfdjywab>2cJ`_b5+WJo83e ztAbgcmG&-J;&#|$5@q^$BYS|UiD!cGforlMX0Nonql08aRAsL&s}Tk#2g3EWzKTk& znlQeK%7vMy-PlC1-l)k4>%zy+TZfCgqNWuc{Q0}FbCuezO~$0+ffL0$1Ad`AOEFaF z9GRJI{zMUjTb5piug+ES zz2*}2iPYWHd9#CcVNGi*^KXx5fY~3)Cp7dk9V*Ytv>GoM}V< zHrd`fJHpUDUF(Oda1|&w&K^Mk<|C9x(uig~NvLV|ee$n0mT8SyPx7247V&Md3QAn; zA|+khk8yitEVIq-WKLBxmA?n)Y@B4N@mN=wbO`$%Y$#J08=XATC@3R-CAa zWLUuB%I+c5XB&4rnkiTX9gk&ksc}SJe|Brz{RaynGet^;q+t zxTm}Yk;aaXNcZ0v^;sDbBdh^qJlPK;LOUu+Zz7ZDk+_KY9YK9rqoVj0_Nqp17l$*# zP`DqO@33JK_gmx-7@ZGj+{O&FZ%5jN^9b@`vZjuSiltAy_tU=lIl$9Angs8dn*gV& z8y1b5O$9!?d$94C=?0LmswL=#~+A!`Zd`6fZ8_tP^H zquC(?I0)x;WXA+V4tsl76TI^G(p4QPdQr0!eV0wX5q31;=B;Z~xa7doo1`kY@d+JWYI;^U5dXGqYj}(oOHd1m{GdYDxQC#(-xs~ zbZjYn|5Sx+MCE>Iz$n|dz`(A0e$XeQiMA!buVn!)VE}X4L=Yifl|KvF?E4&V zfTOr_L>h_E*C^AOz+sc=-GXPT0%G>4?w%f82~gBRfmLMm`M>;x@mjUpKu?e8>+53| z9g-qEOEn7{^7Z#00+@*fc0Kq!m>D0}7u`%2tr~Y(T%kM4clPZAxU{SdKeGj|l7LOMd6TcqJ@LKkMEpCjiE|Dk3^-tLW@ZLRQZ1?; zg;BVFzVdkRdTea0$SjP02ePhr^<}XwPW2M=u0eo=_V{bFdnc#NBF|gn14%8;TPdyAWJZ?{~sr?UEz-3fJ}K zm=SJ{)e<40DG-Qkjdm#p#Cf5 z{jMNQ!6oxm()>s2y`#7;fye2`ZVHe6b_g%uqizYU;4HF>7M8clTx@bg72J$ETD zj!UO==bDrQ{jWAu=bst*jh-S7LXxsFtshgVlJqgR&lZ z&II5$3}^K6B+u);%_MTp`7f%GcUY{AjQ^!F!l7U5W;IP0Hy++_Y9aV$dBh{5SvlHu zh>H%HSK0felDthR{d1MPg(39m%`_;D%IM~d+@=#D&yym>1)6nllL2BE(r~`o9`$^y z+&J)CSuu5K2g=;#d<~uYN8{AU8XY$)aj-g+jzf7){gfSHrd8w$<;vIHukYW6xc;?1 z4n(zF;!aOb^LY~${tbnDrG&vj@?+p0C!W#$1|cFdQCDS=p9P7n*4NwY(axaVtcxFj z{%3?xl)Z<&pM8+NlgY%ax?T|#?b~!Z$?@m$BZfix-ED?P*Ye#5x;Rb)TBnN-Ku(2v zYgt*uJ_Nk+Gp7vZDj~Jj7GEDlhYSstEc!DwYOcUZqH9xaY^0X1feqp#@?JCb0YC-K zE3hg$xCQZ6eZ54bFWXSPNC{q(a<^k+$1H)>r+Dh*xn6h7%rU=pJR{3N_Yj{t+s}@) z&K*U~?;t)|>>S~Mfy()_`EsGQSAAm1ryn~dL>{q6+oNU?v89VUgGTAeJq{5yB1A|y zc6vvk^<`=^A<10jO85ENt;?#PJYF@oegR=%rmL3)%iQ@J8!YPU>y?HZrKC6N7ppMh zn4q7057%X-n%Seah)=RHET>_pb`!zF{r6{+M&N%fqO&mOvJdfTdO$5l0Bpb(BYJI+ ztFHy-#tDPQGXPC;PU8k;re$4RDUaAwF#*&TLd&`|k2uiR@l+PW)8jdycdu`06mjbH zt-7F5jNlawv0Kacdizr*&e3;YAFW+im1X&bE{1fqT)J3d$OJULt#!QP>RSucU^H~- z9!=kU8lz<2EP)|&gx$;|QpLA}^xhdaBpQ5G2ykv>^q!)4ELYyc(5N3MJd#gZ8ebM5 zYZJ*s5B?R?S-(h7|3Y@Ou${LPJ2aHinzIYC;}LP+SuJ{oPvEV9V?N$^!PE{FixMm6 z^a5w*@7`kkk6nlSSDdT8U^GU|_;wi5?BelpC7flpX<{ z0jOzx+yaLN#Ubw;@)YC=OphoE53&Tg<;8@8im?hxCI@Iv>doD}^FdE2o5fzxloI`#ksaJoj_o*K=Rj`#!&B zX(F;$YA+ujpNN_1Wg9-e9kzUY{2qID0C(JIEysaB{`)p2m-tFLj?4lVJAE!%T;$^` zOBCL^xeK@!x@+ompN~(pf%oHY4$SxB<5Ps1UA|}+?oJy9y;N#0YhD(V5&cs*tKu8K z0KY)Yw{xGrfB)nuS)p(>!Ktme?WDYX_|m&~j~;)XdG{{s-S>+ZFV+utq}v6s)84|g z>_^CAufMjm%w~+t(a6}ohl|`O{@qJs4KZu4hs6xHZZr$Mh^I9CYQWuMSQ)S=yFRRL zu^2v`ZwG^Rcq+1f+i8XiTO1wSA-=KPEN5oW_6N|`6gQXzeZ7YebMz&&0%)@jF7~@T z>y`=qrh<~((+l+W1WLnYQ-fa~Q_^GzG0$H@5A7i6=)uLrj{^4KfuTxr%9rRj_b8F) zO%1L-`5zj5Vh&&AYF3>pq=?V?NLED^muX4-80v{Iw;kctP-s#t+=YDFB>6*^-v=S>K?d!0#xt zJ$c~B)fDz?%l>e$gBbX&hiZNTEU!zu>2I_$W@hR@=<9|c`WVBM&Sqlp=!q|$bi;wc zL?O@W4vWMTO4x;xr&$us zn2Dtn)hMwjW$*nXZ;S{~Wv_?bM9MEhOq>9B=CZDb(_$^`fe{JalczrufKbP=*L^?eR~yy%Mp>L~h;v4c(6d4+V{%`mtVm zusrKg{n4ME;n%zTv$a6zv!Birod1=eBh`_80xmXi^rw^LN`F@(`<_iKF*Udm^S2*A ziY7s`$IjO(upY@M{2w-m8$6a+$`n^8-)YM{;~G47zIM#_M_`EKN>(7d z!Mua!8l!cF7L9z4H2VfTl)X2a6cYA=B7KGS)_=H&K-@43>4th&nX|b0$rP8>8}QTv{8t42tQs7r z5odt_x9G7PG&+jkm{_HM^$iG-r6s4j9n=dd8gcxATUmir0V>moF47nfy+3Ua9T)lp z`Dc#Pkyf8#-6czd+2Yl3W#S=z70tg~GE63NlGVXi_F;%C=xdFKyADwkdCR=@b(2I` zJmyW6zrCT!gq*%aUDrTm4;1(POSjSdOy9*(DT0nf&0#-(kFnN)eqEe#x7mR4p#+Ph zPNif*ovAMR)UZs<&!OV*C1uwj8$yc^>)z3NEqI_RI_;(fn7S@?EMqIa>{SJk;U2y1Ek?<3rKRiGVx%*BWbHOjS)EoksFd z%Bb5cRby7gJWIxBq!{GK7B$83H>PDpdY;tj$bL*J*Z<()eno<;k&~I&D7yR9*R1oy z8jnN7V%w49h@2BZS~ZekMVi!@+|1H=`Pf7L1!6Ya=e&i?>FB5fYJ5i+!Svl8gU-(aatQCgX|D_N*?tn!Vqf3d8Lw+X{ z1&K&KgU2U$8STtCxuD2W`gu6jNd!SGz{2+F`{K*0(D$qN0^pFfYDIB@m>6-+K{BD< zWQ5L~3JKdqI_J8JAUOYRLxqm)+i!HhFz-wTdX8+}y*7E6{bUWT>bGbNnZA2K3BVL; z=2uKA6wcI~7C;k7yFl|;XD~V}d*c2*`^aisxl8#5KB+MLXj(V^)f6}bFW zaT8^@d2x-0AUbh*NhWbw2*Sg%-7pQ>HR}1N`p9v?9%X{yjWYnwIZt;Ps1JseiDO8S z-bkKF>5VFb(uGS1GuxAY;$t&X1UhP+VEVktnafI5M-wB?Se_W9=l-XYPEEIK1^TZ{ z5dYdx;;q!j@YG#JB*Qn|p?tDcdR4s9?Y1sN3pL>q&l+z##+ymWD&Hq`Wk+_9^9gYe z3&XKU^;r7IfLW;bY%zMtdmi00^ly3s6tRHXl^ab63haOR^CeWJ-$IPd3YA}Lx5cT*|S%zfJa^oZ}Q*~Q;>hpwxOB`{|EG6~bjT^uGbL6?nRs{Xp%ijhP6AdN93; zhoT89jl5-CvNh(q}#SmkedL~9`ASj7uW{s3F`4_`?4hhx}hB zr2uQz2^_5>S8_RPc!xV(z&89&zbOf@<0U3-=wKSN*^sk5k!V=eXj~t~CMAd;k|qeQ zEG>-avBHq*e8UHTs|$4g3809VoV>VANawSQ9fdT+kmE7LaKqWbC%eU(w_quN;Tp9L+9Cv+)%()e(7r~q#++16v zP4AdLM2Ly+iNUEeEjTKCaIs&3E(w(TN^?hv{9w?-hPCp7vi z=L-Ar8b8-wrS|-Nky6k8yP-0u`a_c2t`T9keIA6LsdYHZ3XvU8prnZq1oN{poz4!$ zcYg(8DKZ3|!#r1zZ}sgktGLo=IoypaCtmb#`h2_D2{Ve<+O|En#&-!8(bSvT`W@v` zhKi1jMAly`lf?PA4NGkg6B4<5OvBPbxvX3cY_GXUY#ZM5kNfWD{c}vi!NO?ZS;ol> zv?TGt@cg6g9eiN;^qa~4-*CmdI$Kyda^N^P3oFmtqPU>%hM7QgZq~HV%r1MO7npk$C;1g}5Vx#gpHF#%;Ic{<3xB;+E!CL-BtJw!I(T`qI{eAGUen_^}icO>|Fh292X2lw<_->2MbnwRNwbZ8y|lB?yFI&0B6pXJK>BqK8Vr zZLkwnUfXl5a-!G;Z%HqdRhHz{!H+{44!qJ%K}(ipqo0{0Gqj_TV#U}};%DdF2+%7K z`qxI?+W~F6@yFy9Sgsg~I7_^u%5^tvBsNmrZXQC5js*(ZJH`Ngo0PFne_?_0v^_#A z@>1(~II)r2i+d5>uRt6sMK21PzJ!+e&VZJy14uf(kc%3(fKd;>VYoj8JjP;#4CE%-Tk@GLUKGm z69*l;Cbj+N(gt5s9I!1JnBk9!0W&!fRjsJIib|Q-R@gKaOX)bmG&Zst-Z@d*6<7>5 z*^8{N{$j6jPgp5)$cHXee=Y@G8aOP-ds+YvjSxNG>z>|@%5Kei2@Svy1eJ`TcAxsn zDMt%L|205{<~JdgSJ}ry9YoJkZ?Uttac+(>y+^lIZVf%DxlVPMhh%wxAt1ZrXi(rO zMGwOOWI_Lryy}rvs75qplmFglPvg`M=T+(+vR~UlpN?&e1X2OCQufSn0R zP+$#jP|Tw`e6|Mex6bP8l5-+<|Ch9O@qE&G*96O%3W8HP%+Sq7Mb>a6FS&ERk>VKZ zMq45AP&&NxrQQQ}3V5M5^Z3z&_}NuK40-X0&o{E9H?qfVooSl{U6`j}CGqq3gn8Td z-z0mIJ1ewbjvR%*KM%ycC3_L-psySW$U)|tEzW{vhlTS1U1K8z?zs9}S?MYuTog-} zysIoIMn9858oBz>D%E%*NHl<&$J-xfK?|Z)iDo^snzv)UmmJF~?tKJ^q?pII#9gk! zfb}Z|Nrp9kt=>!h$btS#jX0uv{&it6@m6I5%6ingkub2LtKHZIWaW6BP6_x5t@V1i zdThv@3lct;=bMpQt7nb3u6{fKEUK4c8=v~+5!#O2Rbvt&RYJD;peong6d$-AjNWH&V!adHSw5-9Q3w0E6PIjsSz_WW>qM#w= z!8{c#$ktb7G0wxbS7RI+;RiluzE96Aqcpy812F5yh}UTWf)3EDz^6|a3mJ@CQZTJu z()pp&lU_ybQ-2KfzIj4Zr+a&iz?lKBtV*CD!gL3Re0SNK=7YOuFx%Y!-V2u>ltjYP zqq>(T3nEia8qN34xo(!5pls6uT~%6|=?V72U}g3xi=};G3ZptkwI}KTN$g~HQ>yAh z6&W7KKNrth@E*~5M)P)|hi$kasMjpAV8Uiy6VwZM zwQ0Phm(X1ZNOA!3!6&=;i{`dHx>?ELED=^Q{fDtM48>3GL#WK`v`gd7j2E$ycX;M) z=tlqjQHDzqyG#@TQn|~0FHIGqZUJ(g_f-#88@GYvW~k0mZNBJspSnrycCVazQC3x@C3_t1$bu$o6K4W zUz6 z$=|5E;6u%v8ch^HJNIei#xh!nf)ULuA|3ZCK**&ZrRcBVdQI4VUgh+@?NY)%^WecQtea!(&{ywd#8iBH z-xL#Rqt~)o`yzEvGRO2k(r335`##eb0|?*%%x5qR|dU zVf$&9S7Gb7ZPEU^Ovf&+wiI`=yF*B+|tvgF$(EmmKXlXg9iq4 z1QkQ3cABt-K)=Z{GA0FJ(9qSe2yfJV0m5`Z64W6j{eg{95Y9ox ztLST0nnQw6Msd3#w7zd%Uy#(Lp37E9%WrM2RP@N`8O!#6pj{EQKr>r73f5jgj=RJ% z;^Uq*xxkUtZ5SW{js;;HinI{wJk!jV(C$u*UqcNbfcm$)Xt4O=*GkCrTuHif>V$ z0d1*xObumi@ZO0kQPl;aADW{Z5NUhNrPlQvxF{uff7L#Tv{=ghu&cNj&xdW=mix#l z;F~ptS`z`qLk^Zxo+jjQf{$-q7&{e&R>hSuQ!PmJHSM@9_g5rDndO(m>aN`p)t8go zcbVBD8VO$-CO=;<4<>=ipZ}R7j&Pn1d=3-xiEn^$=IM&D{M*86S z+LQ{~y8)18?Ac;8JwfvLtO~Y}DVc)L4Nr2qy48jGvUpT2cFi{1X?TAbIL$gf&V&}X z=Wu>I#UF}=zu8fe%noY6pSuNwW$c+TR3jAt&+*g8eO_BwF7 zL{PPLe$FDQBTXYvQcziI*+h^i&l;8|sQ5>|3`-AGUo@XhEe&DoepbG6nzVu(Z;Oz{ zxwB6glbo6opEZar`U8_|?uQn@N3Q34okKh~)Ggf&6hmpy+BPu5TOy5c;SR1zSrd1_ zM~Xq6HKL$ReO`f*alXMsiJu+a?EO1@7p%mN7}0AsIbjBFQ>ezzjh4uS5-kvYQc7E9 zR5q<-Kq3OKtwskW9sJR2T=UI~#+)h6N_F(=+KNP&Au#58paF_;Nh0m|>=|Wy;5{MY z4CBo>*3Q%X%Lp(0Bk;@7Q1iXhGU~4a)Z8{8IJ=<1fxmiJ$b2OWIYSS&$oxQ+%f>T= z0-Hvhfl{pQ#GB_{MNP`09n^ehyy??8|IM;GaGC_JPt~q_&2ie|AR-=VX2BKt?tgDn z7b1hr3t3l9lNBILH<{tQPG~TYb)NQS!^pn(;YrLCHv?kSgc+Ec6PJlO7K<&5V5az# zMKAJCFY8?wj!^GDoN_Yn0=*`S(|%B^B-wxV-Xs)RQsebud32n(K}~<)-8Znmab%#l zzCLpBxj$v-IbFJqg{n@n4na5;|r=r2H4k za!{?z(mLYI>no{O(i+tr>k@Q4gI-x$`Vc$gTUl;JM$5{Uz&lx0cM1*&$|*c6Vf3`- zwKM`oD%qjW?Q8|dJToZi{VMoWP`3#wCo&TAY|Fj>GdM%XZSHLlR(~p^Y!FzFIM!AZGP7Dz;rBu{zXc?q2u>|C(8Uz4z^`2 zyF3>t>{18gjx`8MljMF7epA`yOep<%U96#cW$ILsBg)?wMo|HT9^k8r-I1(G1fUs} z87*zBQZa#Kl84-A{lh%i;(^Y$`pGa3X&lUj!wwJqT6!AL4ou(9(qCbWmR4qa+}LQw zbS5l{P9YowL$j>c`th9AOzu`5u`|;U;g}{6`jpb3O-N>MF5)qb$^+(yc0PhKu5&N}HyrQZ>|x zYpkh)kET^xMa-?5iK#+VB;QGTzx56Ozy5#yYklkfXRTzPz0cn7dEc|&{XEa!@m3bb zqL6(MK0ZECQpxlk6}(f5!HvD}6*ABWEmoYvoo{Bx(nYx?K5U5c%D+3~sT9pn9Km^$CeIP^R=?c6D`iaq+#Y z_2YvOXSmYB=4P!waM8iRL2A9#ns(Nj2C;Iq`t!<8TiTH!%%hZ%{wp#UwB|!i&}Yz4 zt+5ElCMDe3p&D;;YDU1tfvBBQFoMB$4&d9jBf)9O5`A>(Yoe!=edp!VN9VVd5L1!( zR7@Y`B+_@_xPb#QX_)E;9YGo^2>E$!#U@q7Q3^z5wJ@K`eJ1MZ`VB2EaKu%7J&@AU z6h|tDVRbb&X00~U7te|Yw7tGP8oY38&f?fpAZul%D3@gtXv=FX3i6qmI>9Juwq8=|l^JI6&?Zt;5$_9lAZTC_fv>G|=t!VaUJ2LJ@ z)&@WsGk_Hid_R|q^U9;=-oT-P7_N}m7H0|FZvEMgLk)xaJtWWb=%Zi1+9gRUm7G$X zu~-TlyI;l-YWY(7D`?%8jbFotSv$UC-n7dbr>wv9`k?E8)eT&nZ;+}>nHvrHj9(gb ztEv2lnMaV~j6lrbjdRu4{fy(NMoI2Zo!bjkiB*_EAoaO!e|)+1+k(jHZGyAz$#;nq zj|alV$1)n?+M2l;5GV!nfg|7xI*`QUQZT6yIfCIn2o$25OxZ6=5F*GMqf=ukF_h#y zz~me_XYJOG&vJnr;42*Q@jo%VU3p<(U?8~HwGr=Ad;#U^YD1GWMz_o71H{g$PNMcY z@v_pUvk4L=0)0YkG+>(SK(=Dy6wU@ z?d2r;H~mYrhZof`%d1{tJ0=e=8er+L(=a9Rp5+6DU4^Sh*!f>-%dK0CREgoZp=!+B zth~i}wD*l+3M5p~X=YIM7Q#lM;I^?w%|um7N@=JM)kUUg(xw@87^fCd+)KLJ$xo@&r}Zr-<^B-{r0Jh5`hr( zR$9_Nq%W=T%i#tb8iWA75Pq|CHg!N{ER60yC~~;DZ`V|_{Y)#_$6GBXZ0R8i^!Ff# zs8*fS&?wm@jN@2JKTe64$9<#e8#n!A=CBEUIBA*>Xuff!k*3PUK*y+ViJ$8=Bh{eQ z_9v~831h;EEh^ez)_6XrdBadLm6N=*OPDe*B1@e7Wy3J^h=HqABT#wF2I-x@kr*3~K79(`3 zFmrCDh**(RTU)95;m||p+Kp1v_h;4lQ}jMhy_(U&_vQj&LW)w$68y@@w5*&nEkkOd zzl0nMY0;myz`TqtJ1K?K-8jRqD3OCb5WgaOaQ+w5X8YZ8GpP3W(~lBqms=b4PNRRv z@hr?CZDEHP)>yi@9d0?5?u_&w2#Ubw8ENdQvd|E(I(sD9To)%n+=6357I{987>(~Z zgPsOl%f=cb--3b4a-n4UdT8j8fGeB7@&$valWgb6IhAIU-CyPwy*}XGm3^u@GN0Ks z@EAm>ML1!5Z8n`HS+V`dp2|^gvIS|{X0&MN4`eF_rl+T?nvbDSV4`wy@IQ>U{|nYv zw^HUf(eJ!vE=c3!zUxDW0%U7!rMPUM7J+`w3SHWW7MDF= zAqPi5wo6qmj8dYQ%V(md)z#Glu-JonNIJX}z=ak?a9pC>YMZ|COTmmIn6QHZ=t=t< z=Vlj*9m<~Nl0Vtd{^hY}GG(wJ%&hoDLrqOhVfW;$qa%_2%zqXEkB+S{o@~TnM^J^gOG`%jvX>Gl`?qIL$ag)_?{TYjiS1E(fhz02 zv5=_V2w3l_y;FKJT>bBC&C>!(l4CPr)xB+N-=0S3bXJc=sZpIEu5qQP%jKs&+7S4B{NT_HXJy(`#H-f2pe6>Qyjijtq^|w!G9C zLAxCXYgyGZ&3d^7d`CBcS5s3adc6xB*^n9YW!b(}EXYzh+8|t8qAq10IC_LIH`=_n zrUGO{JIB~xKN0JA02nCNGs#}-A((hTsR__mao!#E&@!96sk6!68E1NUg>Fq{~RU?vncO;H-Sns9CcH?c|6iWj$%}{EWt4LR(|kPa%~9 zn2BmNa5!fJ&^ZYvjWZnL%>VydDlPa{rX8vCh~8#omMT}emMJa7=K%x|^uVc2Z-3>H z4eB=SG5i(cg-90jgX@PwdB7VuB6*6%ase0RPN5&wSc;ku!Q2QPcw8z(365Fi+{~hk zUxP2$OsJNyvp>ocVVLZIv>#2L2#l2q1p1CZQ8Q!^0dS*t<-cS1>V6r4tsKBC@D^of=CD1Cov(yL6^?3pe9lrwW@E?7gww2P`8rs1 zaPEyx0djGRn^s$+oA|*zz>Hi%**WYY)4(J5gvcfZ6C-ryeh0K+cZnlEu9HM_VYte( z)8dZ}?*QdorbhwguYDAMT&E#MHM~hrC;f1X>Md@R$6)p*wY(e4I6xPlWXTT56(0&J2zcNo*1EoVRSdZaW>y*XgnZX*MVfJOgY0@mtsiyKHsLoji z?d6;ZS{_Fv%$yTg^qovb=t}o_b8)WOGsv$v7CW-Ma_w9-m4|*zmzsFznaeWNG34`m zNy%}Podp~nyKS1|gNZJ5u>|WWjF?+Np{9I=#=c?<5FVJzA`^BKPOYemc4hE@^AmBX z(W|FsMe_AUcnL7}DK?3kZbkdtzIQa?wm`!?EzF6TS@146H@xfD+gDl&o(PnKnH9*S zoRpl#>h|bq;CrxpL~Q&^&gculQZxTqV$TwmDJ7@aw;L15Gh zkkiSsizh(g2U7Rnhv`FA{wpol`%N6vP=wS;?IK9qC{FgVt+a#{2S7(3m{(6Deg8EN z$zkp+K@CZ;w-14k1LzbIiNyIna3}FLQ{5jIxxKvX9%uD4gm{lKetmIiX;QHSQP|%P zaxsTqJr)!h7#J8D>OK8OkDLh^yC{@DR}2;RCTsw0Pq`={Hn+aM-j*m+<7#z;l%F6p+pVcXoeTNp<8M2@ppbyn1?! z(9Hp7b5|SV80p%^?3f4}M?+o>%is_8v#ityBmIrq*`?6Jt>myXv@LAJIOO{y+xGRqZxr{MY6);eN z=1RT3Eht3xE(4s@>B;CU@Ow{&rTsR79&NF3f>zT>!so_bNB%>=9@WAtRx_rzx`X~o znX{rL@H*o`_=(Z$^U~F>8ic(ImeoascWps4{1j$flSYhpk12PGpJFXHakec72W9Pz zlTj`%CX|HWu&`R!GWt-P+UhC0j&XNFMkRJTx4X9d!@AY1RauBo<}ebia2e&9_^vX`(Fo9RfUC8U#{S*66oJcLm*S zzs1(6q6n>!=%e`J?f+W7n`mgTPB5S&W{gc$2Y2_k%&>i_)R6~7M=t_Qn7 zHhATxp!-XVnNv{D0P!-!nar}3F7I%3^oi>#P}L5CR)+)?a(4hNMyXrH?t3sKcLfZ= zLXH?R^%OjBn6tPm_WRE!&$BO|LHlKV3p;BRHr6r@FQ`A!`-z%eWsCyz6OIvLwnzVo zCs6->;$@0H)j#s#;xmN@(ZH_xnO U{k)S39`x~<8d{uxdDcDVZ&juWXaE2J diff --git a/pic/外部图3.png b/pic/外部图3.png deleted file mode 100644 index 646ff2cec59f32ce2e850e385301bae05aa41de9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2946 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 diff --git a/pic/外部图5.png b/pic/外部图5.png deleted file mode 100644 index 7d2d3822a7741a30ebca003f89fcba856789fbfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6154 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 diff --git a/pic/外部图6.png b/pic/外部图6.png deleted file mode 100644 index 428b8a16f3c0b9037fe3400d0e0a5736fcdd352d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3122 zcmeHJe>l_a8edtNyoS6*g}tRX)f;n$3QZwiFD50uelK}RYa^49%}y&hD=e>0gxS@v zm54MZTWID-F&oLSujM5swb3HK#+*6l>W}ls`SDNZulJAVdY=1!?(2T8`~G~M`}$Ci zpgi@~ZC(cgf%Lq7az6?JtuoLoKgep0XWf&vXw9|?f7H_zR4z0f*BIcKL%xSVph}wV z;>k4{TPOafAUp^J<*%$&t#J>dKp@>#FZV+M$>9pAZGw@vLB=_4FjPl}1cDxXX$#S* zUE>-5(h#!0(P{P8+in?9oh1qIINFXCjBVfjG2;HD@w4a)o)}|!MpNmD<_^SPdT_*qz_ zm}*$EaX7pCz^Ur-rOFMIpdGNmbN-)S^DY|8?uQ;U;JtaS_D3dW>@=eId&2E2$T#$* zC)+Ng-x&II$nVN&&!|f%A3{RDZZ8fv{FzE!itn2nXg*Co9mzpJxn4C_w&oWoyJD>} z#FjPh8vDgoweh+i`@LCi_~|F(!Vxw-Vn3xMC^?a-eRlHVwH_pcb^@4}W3YWfEO{SBkbNT+;iE)?o-r$tKv{qP{zIl5$_1K3#cU)iWyD$in9V zNjaD?qdcRCXGuU9#Uh`Qr;S~&qMORL^_FZAmXo@0VK{F3t#VNukX}I=lB8_5YRQNP z+Wz@hzE=Z*=j-pTU5C)PHbhlx9{S11FfX%}%@M`Qks;DEyMtXi{^k?`-rAxmDhY3*e4i9rfG z;TZrem^*lbE$h6Pls0`_);T{hBENrbNGt%nF=EdR*~0@4`Yn5$P1{3QvKMlA;H8Ph zu3T%YdXtXgabZQR$p1mZ`a-8;a3(3x5lN7We>6=_QC49ya7Fp!bAl8G*F?b>7r(0D z46vu{V;-T%I~)l04bv6Gz?M?X1b+H>^gOZ6TY9TMFEggatIV=iA=|N%GF64nHpl1- z%CTL-u+;ORBa$jiF3>-Jn=fR0>NkD(wD7RezX)LSsv;e!UE4jfk|sWm@Ne)#t6EN? z5^_Gi(c@xUE10<97=c{el=e*YR1#a%Gp~l?^&ZjGu@DakuSj-z@73J@NOQKHtV7N3 zIzH4J@bU^TvD#-@YTxwmPvOu137F$HldUo9WSyKdrK%#CqT$_-RM=|Nu6$+G-k_Ay zFN5c9Nn=Vw>RLw0tM5Ig#KOvQVNaFm(x_3opL$hrTCOkd%g=esI@jMKO}GV-RW5e6 zX1JcPgi1!!X)9*#KX4>Oa#Z1pCLd3AtkrJ)d->3*E~Qa2q7dA@RBq!8ZntVRHh1h4 z((2nx9S7+}b#~SR1u3bq9T&to?aAI_&=#?EO?~{oL$7S5DO;ZNt3pBu!;SZVf^;n# zn_{-2Gs_5J#@IiJH@>@skUBP>{tZZ~mkBmkcke6h)kdfQ^84DLG!2B(?KSPQp~aae zj)i{^3hJYr5vWM}SJ=HSkCHaWobN|Nv90O1!hkz;?#zd0FRNpFEo)d)ZW(ke&HS%D zLtn})@{~8jHwhZ!*qX8jSGf9LfqXxw^ZeG-8a!4w>&>&NyzZ-hO&(>=QW40WKjzl| zKC=ZomX=hrAA2hp1YBI43u)o|LJ@_>=fyDE%we!oh|1tO zXC@VGU7-qS8MFNrj8Bn1_%o8W)51hY@%1oYk|{bh4DoPH+x2cLe;>tvh|xCZY?+M? z=zH)~rAkH8s1_z0W=iBUGdDGXIJt;5v%Jh-Q?-XBebu9Mm~?UtAttB!Zq5apa}wIg{uYvG`~w1 zA2HTw7F^ix&CaKD&jF|eDb%;7E*i`dcg4K4RKz>~&Pl}s)Ny82@I{7n&1f$QM( zboc>D`0Xq8U5V~pd2zs6b5nkxQ|Qa>_|mwEmB1y+3k(IjW}2!ZIl27M5y$z?=F_iH z#1(Ob&ml%;<4#p~hlTZRX1w@jvh}M1`WJbukwY{ZZE~<-`8#y$Ti1!nNsAnk&GOSB khKBfBou8a9h(ya;$M0l$GsR4{M(2aP4x`-5UD1@k1C=CBcmMzZ diff --git a/pic/架构图.png b/pic/架构图.png deleted file mode 100644 index 652178226b72d4dd6581cec146894155397d064f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12098 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 SdC>PRhqAIq798>X=|2EVOWh&> diff --git a/pic/类图Modbus.png b/pic/类图Modbus.png deleted file mode 100644 index 10c538164ec4d4e5da1b450671229426523efe6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31118 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 P&qJ&=GF_c%=n(c_Y-I(C diff --git a/pic/类图OPC.png b/pic/类图OPC.png deleted file mode 100644 index 4263293f97afacfd35e5a2f7778e9168b426a0c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25158 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 diff --git a/pic/类图Siemens.png b/pic/类图Siemens.png deleted file mode 100644 index b047c49710ea2a5d674e1276806b2f3420c8de41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22456 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 Date: Fri, 30 Jun 2017 11:43:19 +0800 Subject: [PATCH 62/62] README update. --- Modbus.Net/Modbus.Net.Modbus/README.md | 75 +--------- Modbus.Net/Modbus.Net.OPC/README.md | 44 +----- Modbus.Net/Modbus.Net.Siemens/README.md | 37 +---- Modbus.Net/Modbus.Net/README.md | 176 ++++++++++++++---------- 4 files changed, 105 insertions(+), 227 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/README.md b/Modbus.Net/Modbus.Net.Modbus/README.md index 84fd28e..4822119 100644 --- a/Modbus.Net/Modbus.Net.Modbus/README.md +++ b/Modbus.Net/Modbus.Net.Modbus/README.md @@ -4,77 +4,4 @@ Modbus.Net.Modbus Modbus Implementation of Modbus.Net -Table of Content: -* [Basic Concept](#basic) -* [Address Mapping](#address) -* [Addres Coding](#coding) -* [SubAddress Rules](#subpos) - -## Basic Concept - -Modbus is a serial communications protocol originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs). Simple and robust, it has since become a de facto standard communication protocol, and it is now a commonly available means of connecting industrial electronic devices.(From Wekipedia) - -## Address Mapping - -Modbus has four types of address: Coil, Discrete Input, Input Register and Holding Register. - -Modbus has two address description method: standard and extend. - -The following table could show the full address discription in Modbus. - -Type | Standard | Extend | ----------------- | ----------- | ------------- | -Coil | 00001-09999 | 000001-065536 | -Discrete Input | 10001-19999 | 100001-165536 | -Input Register | 30001-39999 | 300001-365536 | -Holding Register | 40001-49999 | 400001-465536 | - -Standard and Extend address description are all supported in Modbus.Net.Modbus. The only difference is don't write too large number in address. - -The following table shows how to write address in Modbus.Net.Modbus - -Standard Modbus Address | Modbus.Net.Modbus String Address | ------------------------ | -------------------------------- | -00001 | 0X 1 | -00002 | 0X 2 | -09999 | 0X 9999 | -065536 | 0X 65536 | -10001 | 1X 1 | -30001 | 3X 1 | -40001 | 4X 1 | - -## Address Coding - -In Modbus.Net, you can write "0X"(Coil), "1X"(Discrete Input), "3X"(Input Register), "4X"(Holding Register) in Area. - -Don't forget to type a space between Area and Address. - -If you want to use subpos, type string address like this: - -4X 1.12 (Area Address.Subpos) - -## SubAddress Rules - -For 0X and 1X, the scalation is 1/8. This means each address is bool. - -Noticing that you can only read 1X. - -SubAddress System is not activated in 0X and 1X. - -For 3X and 4X, the scalation is 2. This meas each address is short. - -The number of SubAddress is from 0 to 15. - -Caution: Modbus.Net.Modbus SubAddress has a giant difference towards standard Modbus. - -Bit position from Modbus.Net is one less than standard modbus. - -Standard Modbus - -1 0 1 1 1 0 0 0 1 0 0 0 0 1 1 0
-16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 - -Modbus.Net.Modbus - -1 0 1 1 1 0 0 0 1 0 0 0 0 1 1 0
-15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +Doc has been moved to wiki. \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/README.md b/Modbus.Net/Modbus.Net.OPC/README.md index b2870ad..7e52ec9 100644 --- a/Modbus.Net/Modbus.Net.OPC/README.md +++ b/Modbus.Net/Modbus.Net.OPC/README.md @@ -4,46 +4,4 @@ Modbus Implementation of Modbus.Net -Table of Content: -* [Basic Concept](#basic) -* [Address Mapping](#address) -* [Regex System](#regex) -* [Link](#link) - -## Basic Concept - -OPC Protocal implements OPC DA and OPC UA protocal. - -## Address Mapping - -Modbus.Net.OPC has a simple address formatting tool. You can find it from AddressFormaterOPC. - -You need to use messages in BaseMachine and AddressUnit to create an OPC tag. - -Here is a Sample. - -If your tag is "1/15/Value_Opening", 1 is MachineId, 15 is StationId and Value_Opening is point name. - -Your tagGeter code should be. - -```C# -(baseMachine, addressUnit) => return new string[]{baseMachine.Id, ((XXUnitExtend)addressUnit.unitExtend).stationId, addressUnit.Name}; -``` - -If you want change your tag to "1.15.Value_Opening", just set the seperator to '.' . - -## Regex System - -Every tag could be a regex expression, Modbus.Net.OPC will always use regex comparison mode between each tags. - -Like if you want to use a wildcard for first tag(or first directory), input your tagGeter code like this: - -```C# -(baseMachine, addressUnit) => return new string[]{"(.*)", baseMachine.Id, ((XXUnitExtend)addressUnit.unitExtend).stationId, addressUnit.Name}; -``` - -## Link - -The link of OPC DA should like "opcda://PC-Name/OPC-Software-Name". - -The link of OPC UA should like "opc.tcp://PC-Name/Opc-Software-Name". +Doc has been moved to wiki. \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Siemens/README.md b/Modbus.Net/Modbus.Net.Siemens/README.md index 1b775cf..7c2974c 100644 --- a/Modbus.Net/Modbus.Net.Siemens/README.md +++ b/Modbus.Net/Modbus.Net.Siemens/README.md @@ -4,39 +4,4 @@ Modbus Implementation of Modbus.Net -Table of Content: -* [Basic Concept](#basic) -* [Address Mapping](#address) -* [Addres Coding](#coding) -* [SubAddress Rules](#subpos) - -## Basic Concept - -Siemens Protocal is derived by Profibus and Profinet. - -## Address Mapping - -Modbus.Net.Siemens has two types of AddressMapping -- Modbus.Net way or Siemens way. - -But Modbus.Net already decleared the type in AddressUnit, so all of the formatting ways will ignore the address type. - -The following table shows the differences between them. - -Standard Siemens Address | Modbus.Net Address Format | Siemens Address Format | ------------------------- | ------------------------- | ---------------------- | -I0.0 | I 0.0 | I0.0 | -IB0 | I 0 | I0 | -V10.5 | V 10.5 | V10.5 | -VB19 | V 19 | V19 | -DB1.DBD22 | DB1 22 | DB1.DB22 | -DB2.DB35.1 | DB2 35.1 | DB2.DB35.1 | - -## Address Coding - -The Coding of Modbus.Net.Siemens is the same as standard siemens protocal. - -## SubAddress Rules - -SubAddress Rules is the same as standard siemens protocal. - -Area length will always be 1. +Doc has been moved to wiki. \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/README.md b/Modbus.Net/Modbus.Net/README.md index b0b2ddd..772a1df 100644 --- a/Modbus.Net/Modbus.Net/README.md +++ b/Modbus.Net/Modbus.Net/README.md @@ -97,23 +97,37 @@ List addressUnits = new List 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(10, 300, true); +TaskManager task = new TaskManager(10, true); task.AddMachine(new SiemensMachine(SiemensType.Tcp, "192.168.3.11", SiemensMachineModel.S7_300, addressUnits, true, 2, 0)); -task.ReturnValues += (returnValues) => +task.InvokeTimerAll(new TaskItemGetData(returnValues => { - value = new List(); + //唯一的参数包含返回值,是一个唯一标识符(machine的第二个参数),返回值(类型ReturnUnit)的键值对。 if (returnValues.ReturnValues != null) { - value = from val in returnValues.ReturnValues select val.Key + " " + val.Value.PlcValue; - siemensItems.Dispatcher.Invoke(() => siemensItems.ItemsSource = value); + lock (values) + { + var unitValues = from val in returnValues.ReturnValues + select + new Tuple( + addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); + values = from unitValue in unitValues + select + new TaskViewModel() + { + Id = unitValue.Item1.Id, + Name = unitValue.Item1.Name, + Address = unitValue.Item1.Address.ToString(), + Value = unitValue.Item2 ?? 0, + Type = unitValue.Item1.DataType.Name + }; + } } else { Console.WriteLine($"ip {returnValues.MachineId} not return value"); } -}; -task.TaskStart(); +}, MachineGetDataType.CommunicationTag, 5000, 60000)); ``` @@ -129,26 +143,19 @@ More important, you can extend and implement your own field in UnitExtend in eve 3. Add a machine to TaskManager. Add a machine like siemens machine to the task manager. -4. Implement ReturnValues event. -The argument return values is a key value pair. The architechture is: - -* Key : the link address of machine (in sample is the second parameter). -* Value : Dictionary. -* Key : CommunicationTag/Address(string) in AddressUnit. -* Value : ReturnUnit. -* PlcValue : The return data, all in double type. -* UnitExtend : UnitExtend in AddressUnit. You should cast this class to your own class extends by UnitExtend. +4. Add a TaskItem for one machine or all Machines. + Modbus.Net implement TaskItemGetDatas and TaskItemSetDatas as the default. ## Tutorial This platform has three level APIs that you could use: Low level API called "BaseUtility"; Middle level API called "BaseMachine"; High level API called "TaskManager". -###BaseUtility -BaseUtility is a low level api, in this level you can get or set data only by byte array or object array. Here is an example. +### Utility +IUtilityProperty is a low level api, in this level you can get or set data only by byte array or object array. Here is an example. ```C# string ip = "192.168.0.10"; -BaseUtility utility = new ModbusUtility(ModbusType.Tcp, ip, 0x02, 0x00); -object[] getNum = utility.GetDatas("4X 1", new KeyValuePair(typeof(ushort), 4)); +IUtilityProperty utility = new ModbusUtility(ModbusType.Tcp, ip, 0x02, 0x00); +object[] getNum = utility.InvokeUtilityMethod?.GetDatas("4X 1", new KeyValuePair(typeof(ushort), 4)); ``` BaseUtility is an abstract class. You can check all apis in BaseUtility.cs in Modbus.Net project. @@ -157,24 +164,25 @@ To use BaseUtility, follow these steps. 1.New a BaseUtility instance, but remember BaseUtility is an abstract class, you should new class inherit from it. ```C# -BaseUtility utility = new ModbusUtility(ModbusType.Tcp, ip, 0x02, 0x00); +IUtilityPropety utility = new ModbusUtility(ModbusType.Tcp, ip, 0x02, 0x00); ``` -2.Use GetData and SetData Api in BaseUtility, like +2.Use GetData and SetData Api in IUtilityMethodData, like ```C# -object[] getNum = utility.GetDatas("4X 1", new KeyValuePair(typeof(ushort), 4)); +object[] getNum = utility.InvokeUtilityMethod?.GetDatas("4X 1", new KeyValuePair(typeof(ushort), 4)); -utility.SetDatas("4X 1", new object[] { (ushort)1, (ushort)2, (ushort)3 }); +utility.InvokeUtilityMethod?.SetDatas("4X 1", new object[] { (ushort)1, (ushort)2, (ushort)3 }); ``` Remember force set type of numbers because GetData and SetData Apis are type sensitive. You can also use async functions like ```C# -object[] getNum = await utility.GetDatasAsync("4X 1", new KeyValuePair(typeof(ushort), 4)); +object[] getNum = await utility.InvokeUtilityMethod?.GetDatasAsync("4X 1", new KeyValuePair(typeof(ushort), 4)); ``` -###BaseMachine -BaseMachine is a middle level api, in this level you could get and set datas in a managable data structure for a single machine. +### Machine + +IMachineProperty is a middle level api, in this level you could get and set datas in a managable data structure for a single machine. To understand this class, you have to see the AddressUnit first. ```C# public class AddressUnit @@ -205,9 +213,9 @@ For some reasons, AddressUnit has two keys: Id and CommunicationTag, one is inte * Unit : Unit of the Address. For example "¡æ". * UnitExtend : If you want to get something else when value returns, extend the class and give it to here. -Then using BaseMachine like this. +Then using IMachineProperty like this. ```C# -BaseMachine machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List() +IMachineProperty machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List() { machine = new ModbusMachine(ModbusType.Rtu, "COM3", new List() { @@ -219,18 +227,18 @@ machine = new ModbusMachine(ModbusType.Rtu, "COM3", new List() machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator); machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator); machine.AddressCombiner = new AddressCombinerPercentageJump(20.0); -var result = machine.GetDatas(MachineGetDataType.CommunicationTag); +var result = machine.InvokeMachineMethods?.GetDatas(MachineGetDataType.CommunicationTag); var add1 = result["Add1"].PlcValue; var resultFormat = result.MapGetValuesToSetValues(); -machine.SetDatas(MachineSetDataType.CommunicationTag, resultFormat); +machine.InvokeMachineMethods?.SetDatas(MachineSetDataType.CommunicationTag, resultFormat); ``` To use BaseMachine, follow these steps. -1.New a BaseMachine instance. Remeber BaseMachine is an abstract class. +1.New a IMachineProperty instance. ```C# -machine = new ModbusMachine(ModbusType.Rtu, "COM3", new List() +IMachineProperty machine = new ModbusMachine(ModbusType.Rtu, "COM3", new List() { new AddressUnit() {Id = "1", Area = "4X", Address = 1, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, new AddressUnit() {Id = "2", Area = "4X", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, @@ -259,8 +267,8 @@ There are 4 AddressCombiners implemented in the platform. 3.Use GetDatas Api. ```C# -var result = machine.GetDatas(MachineGetDataType.CommunicationTag); -//var result = await machine.GetDatasAsync(MachineGetDataType.CommunicationTag); +var result = machine.InvokeMachineMethods?.GetDatas(MachineGetDataType.CommunicationTag); +//var result = await machine.InvokeMachineMethods?.GetDatasAsync(MachineGetDataType.CommunicationTag); ``` 4.Retrive data from result. @@ -275,13 +283,15 @@ var resultFormat = result.MapGetValuesToSetValues(); 6.SetData to machine or another machine. ```C# -machine.SetDatas(MachineSetDataType.CommunicationTag, resultFormat); +machine.InvokeMachineMethods?.SetDatas(MachineSetDataType.CommunicationTag, resultFormat); ``` There is also a SetDatasAsync Api. -machine.SetDatas has two types. It is referenced as the first parameter. +machine.SetDatas has four types. It is referenced as the first parameter. 1. MachineSetDataType.Address: the key of the dictionary of the second parameter is address. 2. MachineSetDataType.CommunicationTag: the key of the dictionary of the second parameter is communication tag. +3. MachineSetDataType.Id: the key of the dictionary of the second paramenter is ID. +4. MachineSetDataType.Name: the key of the dictionary of the second paramenter is name. ### TaskManager TaskManager is a high level api that you can manage and control many machines together. Remenber if you want to use this class, all communications must be asyncronized. @@ -294,20 +304,33 @@ List addressUnits = new List new AddressUnit() {Id = 1, Area = "V", Address = 3, CommunicationTag = "D2", DataType = typeof (float), Zoom = 1} }; task.AddMachine(new SiemensMachine(SiemensType.Tcp, "192.168.3.11",SiemensMachineModel.S7_300, addressUnits, true)); -task.ReturnValues += (returnValues) => +task.InvokeTimerAll(new TaskItemGetData(returnValues => { - value = new List(); - if (returnValues.Value != null) - { - value = from val in returnValues.Value select val.Key + " " + val.Value.PlcValue; - siemensItems.Dispatcher.Invoke(() => siemensItems.ItemsSource = value); - } - else - { - Console.WriteLine($"ip {returnValues.Key} not return value"); - } -}; -task.TaskStart(); + if (returnValues.ReturnValues != null) + { + lock (values) + { + var unitValues = from val in returnValues.ReturnValues + select + new Tuple( + addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); + values = from unitValue in unitValues + select + new TaskViewModel() + { + Id = unitValue.Item1.Id, + Name = unitValue.Item1.Name, + Address = unitValue.Item1.Address.ToString(), + Value = unitValue.Item2 ?? 0, + Type = unitValue.Item1.DataType.Name + }; + } + } + else + { + Console.WriteLine($"ip {returnValues.MachineId} not return value"); + } +}, MachineGetDataType.CommunicationTag, 5000, 60000)); ``` To use the TaskManager, use following steps. @@ -327,28 +350,35 @@ List addressUnits = new List task.AddMachine(new SiemensMachine(SiemensType.Tcp, "192.168.3.11", SiemensMachineModel.S7_300, addressUnits, true)); ``` -3.Register the ReturnValue Event. +3.Add a get value cycling task. You can handle return values with your own code (ReturnValue event before 1.3.2). ```C# -task.ReturnValues += (returnValues) => +task.InvokeTimerAll(new TaskItemGetData(returnValues => { - value = new List(); - if (returnValues.Value != null) - { - value = from val in returnValues.Value select val.Key + " " + val.Value.PlcValue; - siemensItems.Dispatcher.Invoke(() => siemensItems.ItemsSource = value); - } - else - { - Console.WriteLine($"ip {returnValues.Key} not return value"); - } -}; -``` -The ReturnValues' key is the machineToken, this sample is "192.168.3.11". -And the value is the same as the machine.GetDatas returns. - -4.Start the TaskManager. -```C# -task.TaskStart(); + if (returnValues.ReturnValues != null) + { + lock (values) + { + var unitValues = from val in returnValues.ReturnValues + select + new Tuple( + addressUnits.FirstOrDefault(p => p.CommunicationTag == val.Key), val.Value.PlcValue); + values = from unitValue in unitValues + select + new TaskViewModel() + { + Id = unitValue.Item1.Id, + Name = unitValue.Item1.Name, + Address = unitValue.Item1.Address.ToString(), + Value = unitValue.Item2 ?? 0, + Type = unitValue.Item1.DataType.Name + }; + } + } + else + { + Console.WriteLine($"ip {returnValues.MachineId} not return value"); + } +}, MachineGetDataType.CommunicationTag, 5000, 60000)); ``` 5.And don't forget that there is also a SetDatasAsync Api in the TaskManager. @@ -462,8 +492,6 @@ You need to implement three functions. public override void SetConnectionType(int connectionType) protected override async Task GetDatasAsync(byte slaveAddress, byte masterAddress, string startAddress, int getByteCount) public override async Task SetDatasAsync(byte slaveAddress, byte masterAddress, string startAddress, object[] setContents) -public override bool GetLittleEndian -public override bool SetLittleEndian ``` And don't remember set default AddressTranslator, slaveAddress, masterAddress and Protocal. ```C# @@ -509,8 +537,8 @@ public class AddressFormaterModbus : AddressFormater ## Addition -### For Subpos System -Subpos system is implemented for reading and writing of bits. +### For Subaddress System +Subaddress system is implemented for reading and writing of bits. ```C# public class AddressUnit {

icn+`)%>uju0onqB$v?){>{3cG+BN!S(I# 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 CRMGSR literal 0 HcmV?d00001 diff --git a/pic/UML/ENG/Architecture Graph.vsdx b/pic/UML/ENG/Architecture Graph.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..aab6d7d2a50513a20447600ff7b44b44c2067555 GIT binary patch literal 34810 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