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