2016-01-20 update 2 add comment and change all code to visual studio 2015 and .net framework 4.6

This commit is contained in:
parallelbgls@outlook.com
2016-01-20 17:25:04 +08:00
parent 089e88d1bf
commit fcb4432a98
36 changed files with 688 additions and 465 deletions

View File

@@ -13,13 +13,15 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CrossLampControl.WebApi</RootNamespace> <RootNamespace>CrossLampControl.WebApi</RootNamespace>
<AssemblyName>CrossLampControl.WebApi</AssemblyName> <AssemblyName>CrossLampControl.WebApi</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews> <MvcBuildViews>false</MvcBuildViews>
<UseIISExpress>true</UseIISExpress> <UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort /> <IISExpressSSLPort />
<IISExpressAnonymousAuthentication /> <IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication /> <IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode /> <IISExpressUseClassicPipelineMode />
<TargetFrameworkProfile />
<UseGlobalApplicationHostFile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -42,13 +44,13 @@
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" /> <Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" /> <Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" /> <Reference Include="System.Web.Extensions" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Web" /> <Reference Include="System.Web" />
<Reference Include="System.Web.Abstractions" /> <Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" /> <Reference Include="System.Web.Routing" />
@@ -102,6 +104,7 @@
<Private>True</Private> <Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="WebGrease"> <Reference Include="WebGrease">
<Private>True</Private> <Private>True</Private>
<HintPath>..\packages\WebGrease.1.5.2\lib\WebGrease.dll</HintPath> <HintPath>..\packages\WebGrease.1.5.2\lib\WebGrease.dll</HintPath>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0"?>
<!-- <!--
For more information on how to configure your ASP.NET application, please visit For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301879 http://go.microsoft.com/fwlink/?LinkId=301879
@@ -6,68 +6,76 @@
<configuration> <configuration>
<configSections> <configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</configSections> </configSections>
<connectionStrings> <connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-CrossLampControl.WebApi-20140912112502.mdf;Initial Catalog=aspnet-CrossLampControl.WebApi-20140912112502;Integrated Security=True" providerName="System.Data.SqlClient" /> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-CrossLampControl.WebApi-20140912112502.mdf;Initial Catalog=aspnet-CrossLampControl.WebApi-20140912112502;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings> </connectionStrings>
<appSettings></appSettings> <appSettings/>
<!--
有关 web.config 更改的说明,请参见 http://go.microsoft.com/fwlink/?LinkId=235367。
可在 <httpRuntime> 标记上设置以下特性。
<system.Web>
<httpRuntime targetFramework="4.6" />
</system.Web>
-->
<system.web> <system.web>
<authentication mode="None" /> <authentication mode="None"/>
<compilation debug="true" targetFramework="4.5" /> <compilation debug="true" targetFramework="4.6"/>
<httpRuntime targetFramework="4.5" /> <httpRuntime targetFramework="4.5"/>
</system.web> </system.web>
<system.webServer> <system.webServer>
<modules> <modules>
<remove name="FormsAuthentication" /> <remove name="FormsAuthentication"/>
</modules> </modules>
<handlers> <handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="OPTIONSVerbHandler" /> <remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler" /> <remove name="TRACEVerbHandler"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers> </handlers>
</system.webServer> </system.webServer>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" /> <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" /> <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-5.2.0.0" newVersion="5.2.0.0" /> <bindingRedirect oldVersion="1.0.0.0-5.2.0.0" newVersion="5.2.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" /> <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" /> <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234"/>
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
<entityFramework> <entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters> <parameters>
<parameter value="mssqllocaldb" /> <parameter value="mssqllocaldb"/>
</parameters> </parameters>
</defaultConnectionFactory> </defaultConnectionFactory>
<providers> <providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
</providers> </providers>
</entityFramework> </entityFramework>
</configuration> </configuration>

View File

@@ -4,11 +4,22 @@ using System.Linq;
namespace ModBus.Net namespace ModBus.Net
{ {
/// <summary>
/// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯
/// </summary>
public abstract class AddressCombiner public abstract class AddressCombiner
{ {
/// <summary>
/// 组合地址
/// </summary>
/// <param name="addresses">需要进行组合的地址</param>
/// <returns>组合完成后与设备通讯的地址</returns>
public abstract IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses); public abstract IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses);
} }
/// <summary>
/// 连续的地址将组合成一组,向设备进行通讯
/// </summary>
public class AddressCombinerContinus : AddressCombiner public class AddressCombinerContinus : AddressCombiner
{ {
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses) public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)

View File

@@ -2,11 +2,23 @@
namespace ModBus.Net namespace ModBus.Net
{ {
/// <summary>
/// 地址编码器
/// </summary>
public abstract class AddressFormater public abstract class AddressFormater
{ {
/// <summary>
/// 编码地址
/// </summary>
/// <param name="area">地址所在的数据区域</param>
/// <param name="address">地址</param>
/// <returns>编码后的地址</returns>
public abstract string FormatAddress(string area, int address); public abstract string FormatAddress(string area, int address);
} }
/// <summary>
/// 基本的地址编码器
/// </summary>
public class AddressFormaterBase : AddressFormater public class AddressFormaterBase : AddressFormater
{ {
public override string FormatAddress(string area, int address) public override string FormatAddress(string area, int address)

View File

@@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace ModBus.Net namespace ModBus.Net
{ {
/// <summary> /// <summary>
/// 数据单元翻译器 /// 地址翻译器
/// </summary> /// </summary>
public abstract class AddressTranslator public abstract class AddressTranslator
{ {
@@ -18,7 +18,7 @@ namespace ModBus.Net
} }
/// <summary> /// <summary>
/// 基本的单元转换 /// 基本的地址翻译
/// </summary> /// </summary>
public class AddressTranslatorBase : AddressTranslator public class AddressTranslatorBase : AddressTranslator
{ {

View File

@@ -13,6 +13,12 @@ namespace ModBus.Net
TaskContinuationOptions.None, TaskContinuationOptions.None,
TaskScheduler.Default); TaskScheduler.Default);
/// <summary>
/// Run async method syncronized
/// </summary>
/// <typeparam name="TResult">Return type</typeparam>
/// <param name="func">Async method with return</param>
/// <returns>Return value</returns>
public static TResult RunSync<TResult>(Func<Task<TResult>> func) public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{ {
return AsyncHelper._myTaskFactory return AsyncHelper._myTaskFactory
@@ -22,6 +28,10 @@ namespace ModBus.Net
.GetResult(); .GetResult();
} }
/// <summary>
/// Run async method syncronized.
/// </summary>
/// <param name="func">Async method</param>
public static void RunSync(Func<Task> func) public static void RunSync(Func<Task> func)
{ {
AsyncHelper._myTaskFactory AsyncHelper._myTaskFactory
@@ -31,6 +41,12 @@ namespace ModBus.Net
.GetResult(); .GetResult();
} }
/// <summary>
/// Change async task to async task with cancellation token
/// </summary>
/// <param name="task">Async task</param>
/// <param name="token">Cancellation Token</param>
/// <returns>Task with Cancellation token</returns>
public static Task WithCancellation(this Task task, public static Task WithCancellation(this Task task,
CancellationToken token) CancellationToken token)
{ {
@@ -44,8 +60,8 @@ namespace ModBus.Net
} }
} }
/// <summary>AsyncLock locks across one or several await calls. /// <summary>
/// /// AsyncLock locks across one or several await calls.
/// </summary> /// </summary>
public class AsyncLock public class AsyncLock
{ {
@@ -58,6 +74,10 @@ namespace ModBus.Net
_releaser = Task.FromResult(new Releaser(this)); _releaser = Task.FromResult(new Releaser(this));
} }
/// <summary>
/// Lock the async method. Call like: using (await asynclock.LockAsync())
/// </summary>
/// <returns></returns>
public Task<Releaser> LockAsync() public Task<Releaser> LockAsync()
{ {
var wait = _semaphore.WaitAsync(); var wait = _semaphore.WaitAsync();
@@ -88,6 +108,9 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// AsyncSemaphore semaphore the multi run tasks.
/// </summary>
public class AsyncSemaphore public class AsyncSemaphore
{ {
private readonly static Task _completed = Task.FromResult(true); private readonly static Task _completed = Task.FromResult(true);

View File

@@ -5,6 +5,9 @@ namespace ModBus.Net
{ {
public abstract class BaseConnector public abstract class BaseConnector
{ {
/// <summary>
/// 标识Connector的连接关键字
/// </summary>
public abstract string ConnectionToken { get; } public abstract string ConnectionToken { get; }
/// <summary> /// <summary>
/// 是否处于连接状态 /// 是否处于连接状态
@@ -13,41 +16,41 @@ namespace ModBus.Net
/// <summary> /// <summary>
/// 连接PLC /// 连接PLC
/// </summary> /// </summary>
/// <returns></returns> /// <returns>是否连接成功</returns>
public abstract bool Connect(); public abstract bool Connect();
/// <summary> /// <summary>
/// 连接PLC异步 /// 连接PLC异步
/// </summary> /// </summary>
/// /// <returns></returns> /// <returns>是否连接成功</returns>
public abstract Task<bool> ConnectAsync(); public abstract Task<bool> ConnectAsync();
/// <summary> /// <summary>
/// 断开PLC /// 断开PLC
/// </summary> /// </summary>
/// <returns></returns> /// <returns>是否断开成功</returns>
public abstract bool Disconnect(); public abstract bool Disconnect();
/// <summary> /// <summary>
/// 无返回发送数据 /// 无返回发送数据
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">需要发送的数据</param>
/// <returns></returns> /// <returns>是否发送成功</returns>
public abstract bool SendMsgWithoutReturn(byte[] message); public abstract bool SendMsgWithoutReturn(byte[] message);
/// <summary> /// <summary>
/// 无返回发送数据,异步 /// 无返回发送数据
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">需要发送的数据</param>
/// <returns></returns> /// <returns>是否发送成功</returns>
public abstract Task<bool> SendMsgWithoutReturnAsync(byte[] message); public abstract Task<bool> SendMsgWithoutReturnAsync(byte[] message);
/// <summary> /// <summary>
/// 带返回发送数据 /// 带返回发送数据
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">需要发送的数据</param>
/// <returns></returns> /// <returns>是否发送成功</returns>
public abstract byte[] SendMsg(byte[] message); public abstract byte[] SendMsg(byte[] message);
/// <summary> /// <summary>
/// 带返回发送数据,异步 /// 带返回发送数据
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">需要发送的数据</param>
/// <returns></returns> /// <returns>是否发送成功</returns>
public abstract Task<byte[]> SendMsgAsync(byte[] message); public abstract Task<byte[]> SendMsgAsync(byte[] message);
} }
} }

View File

@@ -5,84 +5,136 @@ using System.Threading.Tasks;
namespace ModBus.Net namespace ModBus.Net
{ {
/// <summary>
/// 向设备设置值的方式
/// </summary>
public enum MachineSetDataType public enum MachineSetDataType
{ {
/// <summary>
/// 地址
/// </summary>
Address, Address,
/// <summary>
/// 通讯标识
/// </summary>
CommunicationTag CommunicationTag
} }
public abstract class BaseMachine : IMachineProperty public abstract class BaseMachine : IMachineProperty
{ {
/// <summary>
/// 设备的Id
/// </summary>
public int Id { get; set; } public int Id { get; set; }
/// <summary>
/// 设备所在工程的名称
/// </summary>
public string ProjectName { get; set; } public string ProjectName { get; set; }
/// <summary>
/// 设备的名称
/// </summary>
public string MachineName { get; set; } public string MachineName { get; set; }
public bool IsConnected /// <summary>
{ /// 是否处于连接状态
get /// </summary>
{ public bool IsConnected => BaseUtility.IsConnected;
return BaseUtility.IsConnected;
}
}
public string ConnectionToken /// <summary>
{ /// 标识设备的连接关键字
get { return BaseUtility.ConnectionToken; } /// </summary>
} public string ConnectionToken => BaseUtility.ConnectionToken;
/// <summary>
/// 地址编码器
/// </summary>
public AddressFormater AddressFormater { get; set; } public AddressFormater AddressFormater { get; set; }
/// <summary>
/// 地址解码器
/// </summary>
public AddressCombiner AddressCombiner { get; set; } public AddressCombiner AddressCombiner { get; set; }
/// <summary>
/// 地址转换器
/// </summary>
public AddressTranslator AddressTranslator public AddressTranslator AddressTranslator
{ {
get { return BaseUtility.AddressTranslator; } get { return BaseUtility.AddressTranslator; }
set { BaseUtility.AddressTranslator = value; } set { BaseUtility.AddressTranslator = value; }
} }
public MachineExtend MachineExtend { get; set; } /// <summary>
/// 与设备实际通讯的连续地址
protected IEnumerable<CommunicationUnit> CommunicateAddresses /// </summary>
{ protected IEnumerable<CommunicationUnit> CommunicateAddresses => AddressCombiner.Combine(GetAddresses);
get { return AddressCombiner.Combine(GetAddresses); }
}
/// <summary>
/// 描述需要与设备通讯的地址
/// </summary>
public IEnumerable<AddressUnit> GetAddresses { get; set; } public IEnumerable<AddressUnit> GetAddresses { get; set; }
/// <summary>
/// 是否保持连接
/// </summary>
public bool KeepConnect { get; set; } public bool KeepConnect { get; set; }
/// <summary>
/// 设备的连接器
/// </summary>
protected BaseUtility BaseUtility { get; set; } protected BaseUtility BaseUtility { get; set; }
/// <summary>
/// 构造器
/// </summary>
/// <param name="getAddresses">需要与设备通讯的地址</param>
protected BaseMachine(IEnumerable<AddressUnit> getAddresses) protected BaseMachine(IEnumerable<AddressUnit> getAddresses)
: this(getAddresses, false) : this(getAddresses, false)
{ {
} }
/// <summary>
/// 构造器
/// </summary>
/// <param name="getAddresses">需要与设备通讯的地址</param>
/// <param name="keepConnect">是否保持连接</param>
protected BaseMachine(IEnumerable<AddressUnit> getAddresses, bool keepConnect) protected BaseMachine(IEnumerable<AddressUnit> getAddresses, bool keepConnect)
{ {
GetAddresses = getAddresses; GetAddresses = getAddresses;
KeepConnect = keepConnect; KeepConnect = keepConnect;
} }
/// <summary>
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
public Dictionary<string, ReturnUnit> GetDatas() public Dictionary<string, ReturnUnit> GetDatas()
{ {
return AsyncHelper.RunSync(GetDatasAsync); return AsyncHelper.RunSync(GetDatasAsync);
} }
/// <summary>
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
public async Task<Dictionary<string,ReturnUnit>> GetDatasAsync() public async Task<Dictionary<string,ReturnUnit>> GetDatasAsync()
{ {
try try
{ {
Dictionary<string, ReturnUnit> ans = new Dictionary<string, ReturnUnit>(); Dictionary<string, ReturnUnit> ans = new Dictionary<string, ReturnUnit>();
//检测并连接设备
if (!BaseUtility.IsConnected) if (!BaseUtility.IsConnected)
{ {
await BaseUtility.ConnectAsync(); await BaseUtility.ConnectAsync();
} }
//如果无法连接,终止
if (!BaseUtility.IsConnected) return null; if (!BaseUtility.IsConnected) return null;
//遍历每一个实际向设备获取数据的连续地址
foreach (var communicateAddress in CommunicateAddresses) foreach (var communicateAddress in CommunicateAddresses)
{ {
//获取数据
var datas = var datas =
await await
BaseUtility.GetDatasAsync<byte>(2, 0, BaseUtility.GetDatasAsync<byte>(2, 0,
@@ -91,15 +143,19 @@ namespace ModBus.Net
Math.Ceiling(communicateAddress.GetCount* Math.Ceiling(communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[ BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName])); communicateAddress.DataType.FullName]));
//如果没有数据,终止
if (datas == null || datas.Length == 0) return null; if (datas == null || datas.Length == 0) return null;
int pos = 0; int pos = 0;
//解码数据
while (pos < communicateAddress.GetCount) while (pos < communicateAddress.GetCount)
{ {
//获取地址
var address = var address =
GetAddresses.SingleOrDefault( GetAddresses.SingleOrDefault(
p => p.Area == communicateAddress.Area && p.Address == pos + communicateAddress.Address); p => p.Area == communicateAddress.Area && p.Address == pos + communicateAddress.Address);
if (address != null) if (address != null)
{ {
//将获取的数据和对应的通讯标识对应
ans.Add(address.CommunicationTag, ans.Add(address.CommunicationTag,
new ReturnUnit new ReturnUnit
{ {
@@ -116,10 +172,12 @@ namespace ModBus.Net
} }
} }
} }
//如果不保持连接,断开连接
if (!KeepConnect) if (!KeepConnect)
{ {
BaseUtility.Disconnect(); BaseUtility.Disconnect();
} }
//返回数据
if (ans.Count == 0) ans = null; if (ans.Count == 0) ans = null;
return ans; return ans;
} }
@@ -130,23 +188,39 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 写入数据
/// </summary>
/// <param name="setDataType">写入类型</param>
/// <param name="values">需要写入的数据字典当写入类型为Address时键为需要写入的地址当写入类型为CommunicationTag时键为需要写入的单元的描述</param>
/// <returns>是否写入成功</returns>
public bool SetDatas(MachineSetDataType setDataType, Dictionary<string, double> values) public bool SetDatas(MachineSetDataType setDataType, Dictionary<string, double> values)
{ {
return AsyncHelper.RunSync(() => SetDatasAsync(setDataType, values)); return AsyncHelper.RunSync(() => SetDatasAsync(setDataType, values));
} }
/// <summary>
/// 写入数据
/// </summary>
/// <param name="setDataType">写入类型</param>
/// <param name="values">需要写入的数据字典当写入类型为Address时键为需要写入的地址当写入类型为CommunicationTag时键为需要写入的单元的描述</param>
/// <returns>是否写入成功</returns>
public async Task<bool> SetDatasAsync(MachineSetDataType setDataType, Dictionary<string, double> values) public async Task<bool> SetDatasAsync(MachineSetDataType setDataType, Dictionary<string, double> values)
{ {
try try
{ {
//检测并连接设备
if (!BaseUtility.IsConnected) if (!BaseUtility.IsConnected)
{ {
await BaseUtility.ConnectAsync(); await BaseUtility.ConnectAsync();
} }
//如果设备无法连接,终止
if (!BaseUtility.IsConnected) return false; if (!BaseUtility.IsConnected) return false;
List<AddressUnit> addresses = new List<AddressUnit>(); List<AddressUnit> addresses = new List<AddressUnit>();
//遍历每个要设置的值
foreach (var value in values) foreach (var value in values)
{ {
//根据设置类型找到对应的地址描述
AddressUnit address = null; AddressUnit address = null;
switch (setDataType) switch (setDataType)
{ {
@@ -166,32 +240,44 @@ namespace ModBus.Net
if (address == null) return false; if (address == null) return false;
addresses.Add(address); addresses.Add(address);
} }
//将地址编码成与实际设备通讯的地址,注意这个地址必须是连续的
var communcationUnits = new AddressCombinerContinus().Combine(addresses); var communcationUnits = new AddressCombinerContinus().Combine(addresses);
//遍历每条通讯的连续地址
foreach (var communicateAddress in communcationUnits) foreach (var communicateAddress in communcationUnits)
{ {
List<object> datasList = new List<object>(); List<object> datasList = new List<object>();
//需要设置的字节数,计数
var setCount = (int) var setCount = (int)
Math.Ceiling(communicateAddress.GetCount* Math.Ceiling(communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[ BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName]); communicateAddress.DataType.FullName]);
//总数
var allBytes = setCount; var allBytes = setCount;
//编码开始地址
var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, var addressStart = AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address); communicateAddress.Address);
while (setCount > 0) while (setCount > 0)
{ {
//编码当前地址
var address = AddressFormater.FormatAddress(communicateAddress.Area, var address = AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address + allBytes - setCount); communicateAddress.Address + allBytes - setCount);
//找到对应的描述地址
var addressUnit = var addressUnit =
GetAddresses.SingleOrDefault( GetAddresses.SingleOrDefault(
p => p =>
p.Area == communicateAddress.Area && p.Area == communicateAddress.Area &&
p.Address == communicateAddress.Address + allBytes - setCount); p.Address == communicateAddress.Address + allBytes - setCount);
//如果没有相应地址,跳过
if (addressUnit == null) continue;
//获取写入类型
Type dataType = addressUnit.DataType; Type dataType = addressUnit.DataType;
switch (setDataType) switch (setDataType)
{ {
case MachineSetDataType.Address: case MachineSetDataType.Address:
{ {
//获取要写入的值
var value = values.SingleOrDefault(p => p.Key == address); var value = values.SingleOrDefault(p => p.Key == address);
//将要写入的值加入队列
datasList.Add(Convert.ChangeType(value.Value, dataType)); datasList.Add(Convert.ChangeType(value.Value, dataType));
break; break;
} }
@@ -204,7 +290,7 @@ namespace ModBus.Net
} }
setCount -= (int) BigEndianValueHelper.Instance.ByteLength[dataType.FullName]; setCount -= (int) BigEndianValueHelper.Instance.ByteLength[dataType.FullName];
} }
//写入数据
await BaseUtility.SetDatasAsync(2, 0, addressStart, datasList.ToArray()); await BaseUtility.SetDatasAsync(2, 0, addressStart, datasList.ToArray());
} }
} }
@@ -216,23 +302,41 @@ namespace ModBus.Net
return true; return true;
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>是否连接成功</returns>
public bool Connect() public bool Connect()
{ {
return BaseUtility.Connect(); return BaseUtility.Connect();
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>是否连接成功</returns>
public async Task<bool> ConnectAsync() public async Task<bool> ConnectAsync()
{ {
return await BaseUtility.ConnectAsync(); return await BaseUtility.ConnectAsync();
} }
/// <summary>
/// 断开设备
/// </summary>
/// <returns>是否断开成功</returns>
public bool Disconnect() public bool Disconnect()
{ {
return BaseUtility.Disconnect(); return BaseUtility.Disconnect();
} }
/// <summary>
/// 将获取的数据转换成可以向设备写入的数据格式
/// </summary>
/// <param name="getValues">获取的数据</param>
/// <returns>写入的数据</returns>
public static Dictionary<string, double> MapGetValuesToSetValues(Dictionary<string, ReturnUnit> getValues) public static Dictionary<string, double> MapGetValuesToSetValues(Dictionary<string, ReturnUnit> getValues)
{ {
if (getValues == null) return null;
return (from getValue in getValues return (from getValue in getValues
select new KeyValuePair<string, double>(getValue.Key, getValue.Value.PlcValue)).ToDictionary(p=>p.Key,p=>p.Value); select new KeyValuePair<string, double>(getValue.Key, getValue.Value.PlcValue)).ToDictionary(p=>p.Key,p=>p.Value);
} }
@@ -251,51 +355,93 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 通讯单元
/// </summary>
public class CommunicationUnit public class CommunicationUnit
{ {
/// <summary>
/// 区域
/// </summary>
public string Area { get; set; } public string Area { get; set; }
/// <summary>
/// 地址
/// </summary>
public int Address { get; set; } public int Address { get; set; }
/// <summary>
/// 获取个数
/// </summary>
public int GetCount { get; set; } public int GetCount { get; set; }
/// <summary>
/// 数据类型
/// </summary>
public Type DataType { get; set; } public Type DataType { get; set; }
} }
/// <summary>
/// 数据单元扩展,返回数据时会同时将其返回
/// </summary>
public class UnitExtend public class UnitExtend
{ {
} }
public class MachineExtend /// <summary>
{ /// 返回的数据单元
/// </summary>
}
public class ReturnUnit public class ReturnUnit
{ {
/// <summary>
/// 返回的数据
/// </summary>
public double PlcValue { get; set; } public double PlcValue { get; set; }
/// <summary>
/// 数据的扩展
/// </summary>
public UnitExtend UnitExtend { get; set; } public UnitExtend UnitExtend { get; set; }
} }
public class AddressUnit public class AddressUnit
{ {
/// <summary>
/// 数据单元Id
/// </summary>
public int Id { get; set; } public int Id { get; set; }
/// <summary> /// <summary>
/// 数据所属的区域Modbus指通讯码PROFINET指数据块 /// 数据所属的区域
/// </summary> /// </summary>
public string Area { get; set; } public string Area { get; set; }
/// <summary>
/// 地址
/// </summary>
public int Address { get; set; } public int Address { get; set; }
/// <summary>
/// 数据类型
/// </summary>
public Type DataType { get; set; } public Type DataType { get; set; }
/// <summary> /// <summary>
/// 放缩比例 /// 放缩比例
/// </summary> /// </summary>
public double Zoom { get; set; } public double Zoom { get; set; }
/// <summary>
/// 小数位数
/// </summary>
public int DecimalPos { get; set; } public int DecimalPos { get; set; }
/// <summary> /// <summary>
/// 通讯标识名称 /// 通讯标识名称
/// </summary> /// </summary>
public string CommunicationTag { get; set; } public string CommunicationTag { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// 单位
/// </summary>
public string Unit { get; set; } public string Unit { get; set; }
/// <summary>
/// 扩展
/// </summary>
public UnitExtend UnitExtend { get; set; } public UnitExtend UnitExtend { get; set; }
} }
@@ -312,11 +458,26 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 设备的抽象
/// </summary>
public interface IMachineProperty public interface IMachineProperty
{ {
/// <summary>
/// Id
/// </summary>
int Id { get; set; } int Id { get; set; }
/// <summary>
/// 工程名
/// </summary>
string ProjectName { get; set; } string ProjectName { get; set; }
/// <summary>
/// 设备名
/// </summary>
string MachineName { get; set; } string MachineName { get; set; }
/// <summary>
/// 标识设备的连接关键字
/// </summary>
string ConnectionToken { get; } string ConnectionToken { get; }
} }
} }

View File

@@ -11,12 +11,13 @@ namespace ModBus.Net
public abstract class BaseProtocal public abstract class BaseProtocal
{ {
/// <summary> /// <summary>
/// 发送数据 /// 协议的连接器
/// </summary> /// </summary>
/// <param name="content">需要发送的数据</param>
/// <returns>数据是否正确接收</returns>
public ProtocalLinker ProtocalLinker { get; protected set; } public ProtocalLinker ProtocalLinker { get; protected set; }
/// <summary>
/// 构造器
/// </summary>
protected BaseProtocal() protected BaseProtocal()
{ {
Protocals = new Dictionary<string, ProtocalUnit>(); Protocals = new Dictionary<string, ProtocalUnit>();
@@ -25,8 +26,8 @@ namespace ModBus.Net
/// <summary> /// <summary>
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
/// </summary> /// </summary>
/// <param name="protocalName">协议的类的名称</param> /// <param name="type">协议的类的GetType</param>
/// <returns></returns> /// <returns>协议的实例</returns>
public ProtocalUnit this[Type type] public ProtocalUnit this[Type type]
{ {
get get
@@ -45,8 +46,15 @@ namespace ModBus.Net
} }
} }
protected Dictionary<string, ProtocalUnit> Protocals { get; private set; } /// <summary>
/// 协议集合
/// </summary>
protected Dictionary<string, ProtocalUnit> Protocals { get; }
/// <summary>
/// 注册一个协议
/// </summary>
/// <param name="linkProtocal">需要注册的协议</param>
protected void Register(ProtocalUnit linkProtocal) protected void Register(ProtocalUnit linkProtocal)
{ {
if (linkProtocal == null) return; if (linkProtocal == null) return;
@@ -56,71 +64,59 @@ namespace ModBus.Net
/// <summary> /// <summary>
/// 发送协议内容并接收,一般方法 /// 发送协议内容并接收,一般方法
/// </summary> /// </summary>
/// <param name="content"></param> /// <param name="content">写入的内容,使用对象数组描述</param>
/// <returns></returns> /// <returns>从设备获取的字节流</returns>
public virtual byte[] SendReceive(params object[] content) public virtual byte[] SendReceive(params object[] content)
{ {
return AsyncHelper.RunSync(() => SendReceiveAsync(content)); return AsyncHelper.RunSync(() => SendReceiveAsync(content));
} }
/// <summary> /// <summary>
/// 发送协议内容并接收,一般方法(异步) /// 发送协议内容并接收,一般方法
/// </summary> /// </summary>
/// <param name="content"></param> /// <param name="content">写入的内容,使用对象数组描述</param>
/// <returns></returns> /// <returns>从设备获取的字节流</returns>
public virtual async Task<byte[]> SendReceiveAsync(params object[] content) public virtual async Task<byte[]> SendReceiveAsync(params object[] content)
{ {
if (ProtocalLinker == null || !ProtocalLinker.IsConnected) if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
{ {
await ConnectAsync(); await ConnectAsync();
} }
return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(content)); if (ProtocalLinker != null)
{
return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(content));
}
else
{
return null;
}
} }
/// <summary> /// <summary>
/// 发送协议,通过传入需要使用的协议内容和输入结构 /// 发送协议,通过传入需要使用的协议内容和输入结构
/// </summary> /// </summary>
/// <param name="unit"></param> /// <param name="unit">协议的实例</param>
/// <param name="content"></param> /// <param name="content">输入信息的结构化描述</param>
/// <returns></returns> /// <returns>输出信息的结构化描述</returns>
public virtual OutputStruct SendReceive(ProtocalUnit unit, InputStruct content) public virtual OutputStruct SendReceive(ProtocalUnit unit, InputStruct content)
{ {
int t = 0; return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content));
//如果为特别处理协议的话,跳过协议扩展收缩
var formatContent = unit.Format(content);
if (formatContent != null)
{
byte[] receiveContent;
if (unit is SpecialProtocalUnit)
{
receiveContent = ProtocalLinker.SendReceiveWithoutExtAndDec(formatContent);
}
else
{
receiveContent = ProtocalLinker.SendReceive(formatContent);
}
if (receiveContent != null)
{
return unit.Unformat(receiveContent, ref t);
}
}
return null;
} }
/// <summary> /// <summary>
/// 发送协议,通过传入需要使用的协议内容和输入结构(异步) /// 发送协议,通过传入需要使用的协议内容和输入结构
/// </summary> /// </summary>
/// <param name="unit"></param> /// <param name="unit">协议的实例</param>
/// <param name="content"></param> /// <param name="content">输入信息的结构化描述</param>
/// <returns></returns> /// <returns>输出信息的结构化描述</returns>
public virtual async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content) public virtual async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content)
{ {
int t = 0; int t = 0;
//如果为特别处理协议的话,跳过协议扩展收缩
var formatContent = unit.Format(content); var formatContent = unit.Format(content);
if (formatContent != null) if (formatContent != null)
{ {
byte[] receiveContent; byte[] receiveContent;
//如果为特别处理协议的话,跳过协议扩展收缩
if (unit is SpecialProtocalUnit) if (unit is SpecialProtocalUnit)
{ {
receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent); receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent);

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace ModBus.Net namespace ModBus.Net
@@ -12,26 +13,29 @@ namespace ModBus.Net
protected BaseProtocal Wrapper; protected BaseProtocal Wrapper;
protected string ConnectionString { get; set; } protected string ConnectionString { get; set; }
public bool IsConnected /// <summary>
{ /// 设备是否已经连接
get /// </summary>
{ public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected;
if (Wrapper == null || Wrapper.ProtocalLinker == null) return false;
return Wrapper.ProtocalLinker.IsConnected;
}
}
public string ConnectionToken /// <summary>
{ /// 标识设备的连接关键字
get { return Wrapper.ProtocalLinker.ConnectionToken; } /// </summary>
} public string ConnectionToken => Wrapper.ProtocalLinker.ConnectionToken;
/// <summary>
/// 地址翻译器
/// </summary>
public AddressTranslator AddressTranslator { get; set; } public AddressTranslator AddressTranslator { get; set; }
/// <summary>
/// 构造器
/// </summary>
protected BaseUtility() protected BaseUtility()
{ {
AddressTranslator = new AddressTranslatorBase(); AddressTranslator = new AddressTranslatorBase();
} }
/// <summary> /// <summary>
/// 设置连接类型 /// 设置连接类型
/// </summary> /// </summary>
@@ -44,7 +48,7 @@ namespace ModBus.Net
/// <param name="belongAddress">从站地址</param> /// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param> /// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param> /// <param name="startAddress">开始地址</param>
/// <param name="getByteCount">获取类型和个数</param> /// <param name="getByteCount">获取字节数个数</param>
/// <returns>接收到的byte数据</returns> /// <returns>接收到的byte数据</returns>
protected virtual byte[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) protected virtual byte[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount)
{ {
@@ -52,32 +56,37 @@ namespace ModBus.Net
} }
/// <summary> /// <summary>
/// 获取数据(异步) /// 获取数据
/// </summary> /// </summary>
/// <param name="belongAddress">从站地址</param> /// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param> /// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param> /// <param name="startAddress">开始地址</param>
/// <param name="getByteCount">获取类型和个数</param> /// <param name="getByteCount">获取字节数个数</param>
/// <returns>接收到的byte数据</returns> /// <returns>接收到的byte数据</returns>
protected abstract Task<byte[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount); protected abstract Task<byte[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount);
/// <summary>
/// 获取数据
/// </summary>
/// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getTypeAndCount">获取类型和个数</param>
/// <returns>接收到的对应的类型和数据</returns>
public virtual object[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, public virtual object[] GetDatas(byte belongAddress, byte masterAddress, string startAddress,
KeyValuePair<Type, int> getTypeAndCount) KeyValuePair<Type, int> getTypeAndCount)
{ {
try return AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getTypeAndCount));
{
string typeName = getTypeAndCount.Key.FullName;
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
byte[] getBytes = GetDatas(belongAddress, masterAddress, startAddress,
(int) Math.Ceiling(bCount*getTypeAndCount.Value));
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount);
}
catch (Exception)
{
return null;
}
} }
/// <summary>
/// 获取数据
/// </summary>
/// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getTypeAndCount">获取类型和个数</param>
/// <returns>接收到的对应的类型和数据</returns>
public virtual async Task<object[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, public virtual async Task<object[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress,
KeyValuePair<Type, int> getTypeAndCount) KeyValuePair<Type, int> getTypeAndCount)
{ {
@@ -95,21 +104,30 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 获取数据
/// </summary>
/// <typeparam name="T">需要接收的类型</typeparam>
/// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getByteCount">获取字节数个数</param>
/// <returns>接收到的对应的类型和数据</returns>
public virtual T[] GetDatas<T>(byte belongAddress, byte masterAddress, string startAddress, public virtual T[] GetDatas<T>(byte belongAddress, byte masterAddress, string startAddress,
int getByteCount) int getByteCount)
{ {
try return AsyncHelper.RunSync(() => GetDatasAsync<T>(belongAddress, masterAddress, startAddress, getByteCount));
{
var getBytes = GetDatas(belongAddress, masterAddress, startAddress,
new KeyValuePair<Type, int>(typeof (T), getByteCount));
return BigEndianValueHelper.Instance.ObjectArrayToDestinationArray<T>(getBytes);
}
catch (Exception)
{
return null;
}
} }
/// <summary>
/// 获取数据
/// </summary>
/// <typeparam name="T">需要接收的类型</typeparam>
/// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getByteCount">获取字节数个数</param>
/// <returns>接收到的对应的类型和数据</returns>
public virtual async Task<T[]> GetDatasAsync<T>(byte belongAddress, byte masterAddress, string startAddress, public virtual async Task<T[]> GetDatasAsync<T>(byte belongAddress, byte masterAddress, string startAddress,
int getByteCount) int getByteCount)
{ {
@@ -125,41 +143,42 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 获取数据
/// </summary>
/// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getTypeAndCountList">获取类型和个数的队列</param>
/// <returns>获取数据的对象数组,请强制转换成相应类型</returns>
public virtual object[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, public virtual object[] GetDatas(byte belongAddress, byte masterAddress, string startAddress,
IEnumerable<KeyValuePair<Type, int>> getTypeAndCountList) IEnumerable<KeyValuePair<Type, int>> getTypeAndCountList)
{ {
try return
{ AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getTypeAndCountList));
int bAllCount = 0;
foreach (var getTypeAndCount in getTypeAndCountList)
{
string typeName = getTypeAndCount.Key.FullName;
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
bAllCount += (int)Math.Ceiling(bCount * getTypeAndCount.Value);
}
byte[] getBytes = GetDatas(belongAddress, masterAddress, startAddress, bAllCount);
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCountList);
}
catch (Exception)
{
return null;
}
} }
/// <summary>
/// 获取数据
/// </summary>
/// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getTypeAndCountList">获取类型和个数的队列</param>
public virtual async Task<object[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, public virtual async Task<object[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress,
IEnumerable<KeyValuePair<Type, int>> getTypeAndCountList) IEnumerable<KeyValuePair<Type, int>> getTypeAndCountList)
{ {
try try
{ {
int bAllCount = 0; var translateTypeAndCount = getTypeAndCountList as IList<KeyValuePair<Type, int>> ??
foreach (var getTypeAndCount in getTypeAndCountList) getTypeAndCountList.ToList();
{ int bAllCount = (
string typeName = getTypeAndCount.Key.FullName; from getTypeAndCount in translateTypeAndCount
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; let typeName = getTypeAndCount.Key.FullName
bAllCount += (int)Math.Ceiling(bCount * getTypeAndCount.Value); let bCount = BigEndianValueHelper.Instance.ByteLength[typeName]
} select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum();
byte[] getBytes = await GetDatasAsync(belongAddress, masterAddress, startAddress, bAllCount); byte[] getBytes = await GetDatasAsync(belongAddress, masterAddress, startAddress, bAllCount);
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCountList); return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount);
} }
catch (Exception) catch (Exception)
{ {
@@ -181,7 +200,7 @@ namespace ModBus.Net
} }
/// <summary> /// <summary>
/// 设置数据(异步) /// 设置数据
/// </summary> /// </summary>
/// <param name="belongAddress">从站地址</param> /// <param name="belongAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param> /// <param name="masterAddress">主站地址</param>
@@ -207,16 +226,28 @@ namespace ModBus.Net
public abstract bool SetTime(byte belongAddress, DateTime setTime); public abstract bool SetTime(byte belongAddress, DateTime setTime);
*/ */
/// <summary>
/// 连接设备
/// </summary>
/// <returns>设备是否连接成功</returns>
public bool Connect() public bool Connect()
{ {
return Wrapper.Connect(); return Wrapper.Connect();
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>设备是否连接成功</returns>
public async Task<bool> ConnectAsync() public async Task<bool> ConnectAsync()
{ {
return await Wrapper.ConnectAsync(); return await Wrapper.ConnectAsync();
} }
/// <summary>
/// 断开设备
/// </summary>
/// <returns>设备是否断开成功</returns>
public bool Disconnect() public bool Disconnect()
{ {
return Wrapper.Disconnect(); return Wrapper.Disconnect();

View File

@@ -38,35 +38,17 @@ namespace ModBus.Net.FBox
} }
} }
public string AuthorizeEndpoint public string AuthorizeEndpoint => BaseAddress + "/connect/authorize";
{
get { return BaseAddress + "/connect/authorize"; }
}
public string LogoutEndpoint public string LogoutEndpoint => BaseAddress + "/connect/endsession";
{
get { return BaseAddress + "/connect/endsession"; }
}
public string TokenEndpoint public string TokenEndpoint => BaseAddress + "/connect/token";
{
get { return BaseAddress + "/connect/token"; }
}
public string UserInfoEndpoint public string UserInfoEndpoint => BaseAddress + "/connect/userinfo";
{
get {return BaseAddress + "/connect/userinfo"; }
}
public string IdentityTokenValidationEndpoint public string IdentityTokenValidationEndpoint => BaseAddress + "/connect/identitytokenvalidation";
{
get {return BaseAddress + "/connect/identitytokenvalidation"; }
}
public string TokenRevocationEndpoint public string TokenRevocationEndpoint => BaseAddress + "/connect/revocation";
{
get {return BaseAddress + "/connect/revocation"; }
}
public string AspNetWebApiSampleApi public string AspNetWebApiSampleApi
{ {

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace DelinRemoteControlBoxTest namespace ModBus.Net.FBox
{ {
public class BoxGroup public class BoxGroup
{ {

View File

@@ -5,7 +5,8 @@ namespace ModBus.Net.FBox
{ {
public class FBoxMachine : BaseMachine public class FBoxMachine : BaseMachine
{ {
public FBoxMachine(FBoxType fBoxType, string connectionString, string localSequence, SignalRSigninMsg msg, IEnumerable<AddressUnit> getAddresses, bool keepConnect) : base(getAddresses, keepConnect) public FBoxMachine(FBoxType fBoxType, string connectionString, string localSequence, SignalRSigninMsg msg,
IEnumerable<AddressUnit> getAddresses, bool keepConnect) : base(getAddresses, keepConnect)
{ {
AddressFormater = new AddressFormaterFBox(); AddressFormater = new AddressFormaterFBox();
AddressCombiner = new AddressCombinerFBox(); AddressCombiner = new AddressCombinerFBox();

View File

@@ -66,9 +66,9 @@ namespace ModBus.Net.FBox
{ {
var readRequestFBoxInputStruct = new ReadRequestFBoxInputStruct(startAddress, (ushort)getByteCount, AddressTranslator); var readRequestFBoxInputStruct = new ReadRequestFBoxInputStruct(startAddress, (ushort)getByteCount, AddressTranslator);
var readRequestSiemensOutputStruct = var readRequestSiemensOutputStruct =
(ReadRequestFBoxOutputStruct)await await
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestFBoxProtocal)], readRequestFBoxInputStruct); Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestFBoxProtocal)], readRequestFBoxInputStruct) as ReadRequestFBoxOutputStruct;
return readRequestSiemensOutputStruct.GetValue; return readRequestSiemensOutputStruct?.GetValue;
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -5,7 +5,6 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using DelinRemoteControlBoxTest;
using Microsoft.AspNet.SignalR.Client; using Microsoft.AspNet.SignalR.Client;
using Newtonsoft.Json; using Newtonsoft.Json;
using Thinktecture.IdentityModel.Client; using Thinktecture.IdentityModel.Client;
@@ -45,36 +44,18 @@ namespace ModBus.Net.FBox
private Timer _timer; private Timer _timer;
private string MachineId private string MachineId => ConnectionToken.Split(',')[0];
{
get
{
return ConnectionToken.Split(',')[0];
}
}
private string LocalSequence { private string LocalSequence => ConnectionToken.Split(',')[1];
get
{
return ConnectionToken.Split(',')[1];
}
}
private static readonly AsyncLock _lock = new AsyncLock(); private static readonly AsyncLock _lock = new AsyncLock();
private bool _connected; private bool _connected;
public override bool IsConnected { get { return _connected; } } public override bool IsConnected => _connected;
private SignalRSigninMsg Msg { get; set;} private SignalRSigninMsg Msg { get; set;}
private Constants _constants; private Constants _constants;
private Constants Constants private Constants Constants => _constants ?? (_constants = new Constants());
{
get
{
if (_constants == null) _constants = new Constants();
return _constants;
}
}
public SignalRConnector(string machineId, string localSequence, SignalRSigninMsg msg) public SignalRConnector(string machineId, string localSequence, SignalRSigninMsg msg)
{ {

View File

@@ -8,23 +8,23 @@
/// <summary> /// <summary>
/// 从输入结构格式化 /// 从输入结构格式化
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">结构化的输入数据</param>
/// <returns></returns> /// <returns>格式化后的字节流</returns>
byte[] Format(InputStruct message); byte[] Format(InputStruct message);
/// <summary> /// <summary>
/// 从对象的参数数组格式化 /// 从对象的参数数组格式化
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">非结构化的输入数据</param>
/// <returns></returns> /// <returns>格式化后的字节流</returns>
byte[] Format(params object[] message); byte[] Format(params object[] message);
/// <summary> /// <summary>
/// 把仪器返回的内容填充到输出结构中 /// 把仪器返回的内容填充到输出结构中
/// </summary> /// </summary>
/// <param name="messageBytes"></param> /// <param name="messageBytes">返回数据的字节流</param>
/// <param name="pos"></param> /// <param name="pos">转换标记位</param>
/// <returns></returns> /// <returns>结构化的输出数据</returns>
OutputStruct Unformat(byte[] messageBytes, ref int pos); OutputStruct Unformat(byte[] messageBytes, ref int pos);
} }
} }

View File

@@ -9,8 +9,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ModBus.Net</RootNamespace> <RootNamespace>ModBus.Net</RootNamespace>
<AssemblyName>ModBus.Net</AssemblyName> <AssemblyName>ModBus.Net</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

View File

@@ -69,10 +69,12 @@ namespace ModBus.Net.Modbus
{ {
try try
{ {
var inputStruct = new ReadDataModbusInputStruct(belongAddress, startAddress, getByteCount % 2 == 0 ? (ushort)(getByteCount / 2) : (ushort)(getByteCount / 2 + 1), AddressTranslator); var inputStruct = new ReadDataModbusInputStruct(belongAddress, startAddress,
getByteCount%2 == 0 ? (ushort) (getByteCount/2) : (ushort) (getByteCount/2 + 1), AddressTranslator);
var outputStruct = await var outputStruct = await
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadDataModbusProtocal)], inputStruct) as ReadDataModbusOutputStruct; Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as
return outputStruct.DataValue; ReadDataModbusOutputStruct;
return outputStruct?.DataValue;
} }
catch catch
{ {
@@ -84,12 +86,12 @@ namespace ModBus.Net.Modbus
{ {
try try
{ {
var inputStruct = new WriteDataModbusInputStruct(belongAddress, startAddress, setContents, AddressTranslator); var inputStruct = new WriteDataModbusInputStruct(belongAddress, startAddress, setContents,
AddressTranslator);
var outputStruct = await var outputStruct = await
Wrapper.SendReceiveAsync(Wrapper[typeof(WriteDataModbusProtocal)], inputStruct) as Wrapper.SendReceiveAsync(Wrapper[typeof (WriteDataModbusProtocal)], inputStruct) as
WriteDataModbusOutputStruct; WriteDataModbusOutputStruct;
if (outputStruct.WriteCount != setContents.Length) return false; return outputStruct?.WriteCount == setContents.Length;
return true;
} }
catch catch
{ {
@@ -106,7 +108,7 @@ namespace ModBus.Net.Modbus
var outputStruct = var outputStruct =
Wrapper.SendReceive(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct) as Wrapper.SendReceive(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct) as
GetSystemTimeModbusOutputStruct; GetSystemTimeModbusOutputStruct;
return outputStruct.Time; return outputStruct?.Time;
} }
catch (Exception) catch (Exception)
{ {
@@ -122,7 +124,7 @@ namespace ModBus.Net.Modbus
var outputStruct = var outputStruct =
Wrapper.SendReceive(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct) as Wrapper.SendReceive(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct) as
SetSystemTimeModbusOutputStruct; SetSystemTimeModbusOutputStruct;
return outputStruct.WriteCount > 0; return outputStruct?.WriteCount > 0;
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -10,31 +10,35 @@ namespace ModBus.Net
{ {
protected BaseConnector _baseConnector; protected BaseConnector _baseConnector;
public string ConnectionToken public string ConnectionToken => _baseConnector.ConnectionToken;
{
get { return _baseConnector.ConnectionToken; }
}
public bool IsConnected /// <summary>
{ /// 设备是否连接
get /// </summary>
{ public bool IsConnected => _baseConnector != null && _baseConnector.IsConnected;
if (_baseConnector == null)
return false;
return _baseConnector.IsConnected;
}
}
/// <summary>
/// 连接设备
/// </summary>
/// <returns>设备是否连接成功</returns>
public bool Connect() public bool Connect()
{ {
return _baseConnector.Connect(); return _baseConnector.Connect();
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>设备是否连接成功</returns>
public async Task<bool> ConnectAsync() public async Task<bool> ConnectAsync()
{ {
return await _baseConnector.ConnectAsync(); return await _baseConnector.ConnectAsync();
} }
/// <summary>
/// 断开设备
/// </summary>
/// <returns>设备是否断开成功</returns>
public bool Disconnect() public bool Disconnect()
{ {
return _baseConnector.Disconnect(); return _baseConnector.Disconnect();
@@ -82,9 +86,8 @@ namespace ModBus.Net
//发送数据 //发送数据
byte[] receiveBytes = await _baseConnector.SendMsgAsync(content); byte[] receiveBytes = await _baseConnector.SendMsgAsync(content);
//容错处理 //容错处理
if (!CheckRight(receiveBytes)) return null; return !CheckRight(receiveBytes) ? null : receiveBytes;
//返回字符 //返回字符
return receiveBytes;
} }
/// <summary> /// <summary>
@@ -94,12 +97,9 @@ namespace ModBus.Net
/// <returns>协议是否是正确的</returns> /// <returns>协议是否是正确的</returns>
public virtual bool CheckRight(byte[] content) public virtual bool CheckRight(byte[] content)
{ {
if (content == null) if (content != null) return true;
{ Disconnect();
Disconnect(); return false;
return false;
}
return true;
} }
/// <summary> /// <summary>
@@ -113,7 +113,7 @@ namespace ModBus.Net
ProtocalLinkerBytesExtend bytesExtend = ProtocalLinkerBytesExtend bytesExtend =
Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as
ProtocalLinkerBytesExtend; ProtocalLinkerBytesExtend;
return bytesExtend.BytesExtend(content); return bytesExtend?.BytesExtend(content);
} }
/// <summary> /// <summary>
@@ -127,7 +127,7 @@ namespace ModBus.Net
ProtocalLinkerBytesExtend bytesExtend = ProtocalLinkerBytesExtend bytesExtend =
Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as
ProtocalLinkerBytesExtend; ProtocalLinkerBytesExtend;
return bytesExtend.BytesDecact(content); return bytesExtend?.BytesDecact(content);
} }
} }
} }

View File

@@ -5,35 +5,35 @@ namespace ModBus.Net
public abstract class ProtocalUnit : IProtocalFormatting public abstract class ProtocalUnit : IProtocalFormatting
{ {
/// <summary> /// <summary>
/// 格式化,将输入结构转换为字节数组 /// 从输入结构格式化
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">结构化的输入数据</param>
/// <returns></returns> /// <returns>格式化后的字节流</returns>
public abstract byte[] Format(InputStruct message); public abstract byte[] Format(InputStruct message);
/// <summary> /// <summary>
/// 格式化,将对象数组转换为字节数组 /// 从对象的参数数组格式化
/// </summary> /// </summary>
/// <param name="message"></param> /// <param name="message">非结构化的输入数据</param>
/// <returns></returns> /// <returns>格式化后的字节流</returns>
public virtual byte[] Format(params object[] message) public virtual byte[] Format(params object[] message)
{ {
return TranslateContent(message); return TranslateContent(message);
} }
/// <summary> /// <summary>
/// 结构化,将字节数组转换为输出结构 /// 把仪器返回的内容填充到输出结构
/// </summary> /// </summary>
/// <param name="messageBytes"></param> /// <param name="messageBytes">返回数据的字节流</param>
/// <param name="pos"></param> /// <param name="pos">转换标记位</param>
/// <returns></returns> /// <returns>结构化的输出数据</returns>
public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos); public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos);
/// <summary> /// <summary>
/// 转换静态方法,把对象数组转换为字节数组。 /// 转换静态方法,把对象数组转换为字节数组。
/// </summary> /// </summary>
/// <param name="contents"></param> /// <param name="contents">对象数组</param>
/// <returns></returns> /// <returns>字节数组</returns>
public static byte[] TranslateContent(params object[] contents) public static byte[] TranslateContent(params object[] contents)
{ {
return BigEndianValueHelper.Instance.ObjectArrayToByteArray(contents); return BigEndianValueHelper.Instance.ObjectArrayToByteArray(contents);

View File

@@ -4,15 +4,15 @@ namespace ModBus.Net.Siemens
{ {
public class SiemensTcpProtocal : SiemensProtocal public class SiemensTcpProtocal : SiemensProtocal
{ {
private ushort _taspSrc; private readonly ushort _taspSrc;
private ushort _tsapDst; private readonly ushort _tsapDst;
private ushort _maxCalling; private readonly ushort _maxCalling;
private ushort _maxCalled; private readonly ushort _maxCalled;
private ushort _maxPdu; private readonly ushort _maxPdu;
private byte _tdpuSize; private readonly byte _tdpuSize;
private string _ip; private readonly string _ip;
private int connectTryCount; 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) 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; _maxPdu = maxPdu;
_tdpuSize = tdpuSize; _tdpuSize = tdpuSize;
_ip = ip; _ip = ip;
connectTryCount = 0; _connectTryCount = 0;
} }
public override byte[] SendReceive(params object[] content) public override byte[] SendReceive(params object[] content)
@@ -51,12 +51,9 @@ namespace ModBus.Net.Siemens
public override async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content) public override async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content)
{ {
if (ProtocalLinker == null || !ProtocalLinker.IsConnected) if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content);
{ if (_connectTryCount > 10) return null;
if (connectTryCount > 10) return null; return await await ConnectAsync().ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null);
return await await ConnectAsync().ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null);
}
return await base.SendReceiveAsync(unit, content);
} }
private async Task<OutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content) private async Task<OutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content)
@@ -71,30 +68,27 @@ namespace ModBus.Net.Siemens
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
connectTryCount++; _connectTryCount++;
ProtocalLinker = new SiemensTcpProtocalLinker(_ip); ProtocalLinker = new SiemensTcpProtocalLinker(_ip);
if (await ProtocalLinker.ConnectAsync()) if (!await ProtocalLinker.ConnectAsync()) return false;
{ _connectTryCount = 0;
connectTryCount = 0; var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst);
var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst); return
return await await
await await ForceSendReceiveAsync(this[typeof (CreateReferenceSiemensProtocal)], inputStruct)
ForceSendReceiveAsync(this[typeof (CreateReferenceSiemensProtocal)], inputStruct) .ContinueWith(async answer =>
.ContinueWith(async answer => {
{ if (!ProtocalLinker.IsConnected) return false;
if (!ProtocalLinker.IsConnected) return false; var inputStruct2 = new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling,
var inputStruct2 = new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling, _maxCalled,
_maxCalled, _maxPdu);
_maxPdu); var outputStruct2 =
var outputStruct2 = (EstablishAssociationSiemensOutputStruct)
(EstablishAssociationSiemensOutputStruct) await
await SendReceiveAsync(this[typeof (EstablishAssociationSiemensProtocal)],
SendReceiveAsync(this[typeof (EstablishAssociationSiemensProtocal)], inputStruct2);
inputStruct2); return outputStruct2 != null;
return true; });
});
}
return false;
} }
} }
} }

View File

@@ -23,12 +23,12 @@ namespace ModBus.Net.Siemens
public class SiemensUtility : BaseUtility public class SiemensUtility : BaseUtility
{ {
private byte _tdpuSize; private readonly byte _tdpuSize;
private ushort _taspSrc; private readonly ushort _taspSrc;
private ushort _tsapDst; private readonly ushort _tsapDst;
private ushort _maxCalling; private readonly ushort _maxCalling;
private ushort _maxCalled; private readonly ushort _maxCalled;
private ushort _maxPdu; private readonly ushort _maxPdu;
private SiemensType _siemensType; private SiemensType _siemensType;
@@ -43,14 +43,14 @@ namespace ModBus.Net.Siemens
_siemensType = value; _siemensType = value;
switch (_siemensType) switch (_siemensType)
{ {
case SiemensType.Ppi: //case SiemensType.Ppi:
{ // {
throw new NotImplementedException(); // throw new NotImplementedException();
} // }
case SiemensType.Mpi: //case SiemensType.Mpi:
{ // {
throw new NotImplementedException(); // throw new NotImplementedException();
} // }
case SiemensType.Tcp: case SiemensType.Tcp:
{ {
Wrapper = ConnectionString == null ? new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu) : new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, ConnectionString); 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_1200:
case SiemensMachineModel.S7_1500: case SiemensMachineModel.S7_1500:
case SiemensMachineModel.S7_200_Smart:
{ {
_tdpuSize = 0x09; _tdpuSize = 0x09;
_taspSrc = 0x4b54; _taspSrc = 0x4b54;
@@ -97,6 +98,10 @@ namespace ModBus.Net.Siemens
_maxPdu = 0x00f0; _maxPdu = 0x00f0;
break; break;
} }
default:
{
throw new NotImplementedException("没有相应的西门子类型");
}
} }
ConnectionType = connectionType; ConnectionType = connectionType;
AddressTranslator = new AddressTranslatorSiemens(); AddressTranslator = new AddressTranslatorSiemens();
@@ -113,9 +118,10 @@ namespace ModBus.Net.Siemens
{ {
var readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(0xd3c7, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator); var readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(0xd3c7, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator);
var readRequestSiemensOutputStruct = var readRequestSiemensOutputStruct =
(ReadRequestSiemensOutputStruct) await await
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestSiemensProtocal)], readRequestSiemensInputStruct); Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)],
return readRequestSiemensOutputStruct.GetValue; readRequestSiemensInputStruct) as ReadRequestSiemensOutputStruct;
return readRequestSiemensOutputStruct?.GetValue;
} }
catch (Exception) catch (Exception)
{ {
@@ -129,12 +135,10 @@ namespace ModBus.Net.Siemens
{ {
var writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(0xd3c8, startAddress, setContents, AddressTranslator); var writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(0xd3c8, startAddress, setContents, AddressTranslator);
var writeRequestSiemensOutputStruct = var writeRequestSiemensOutputStruct =
(WriteRequestSiemensOutputStruct) await await
Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestSiemensProtocal)], writeRequestSiemensInputStruct); Wrapper.SendReceiveAsync(Wrapper[typeof (WriteRequestSiemensProtocal)],
if (writeRequestSiemensOutputStruct.AccessResult == SiemensAccessResult.NoError) writeRequestSiemensInputStruct) as WriteRequestSiemensOutputStruct;
return true; return writeRequestSiemensOutputStruct?.AccessResult == SiemensAccessResult.NoError;
else
return false;
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -174,7 +174,7 @@ namespace ModBus.Net
/// </summary> /// </summary>
private HashSet<BaseMachine> _unlinkedMachines; private HashSet<BaseMachine> _unlinkedMachines;
//private TaskFactory<Dictionary<string,ReturnUnit>> _tasks; //private TaskFactory<Dictionary<string,ReturnUnit>> _tasks;
private TaskScheduler _scheduler; //private TaskScheduler _scheduler;
//private CancellationTokenSource _cts; //private CancellationTokenSource _cts;
/// <summary> /// <summary>
@@ -186,6 +186,9 @@ namespace ModBus.Net
/// </summary> /// </summary>
private Timer _timer2; private Timer _timer2;
/// <summary>
/// 保持连接
/// </summary>
private bool _keepConnect; private bool _keepConnect;
/// <summary> /// <summary>
@@ -208,10 +211,20 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 返回数据代理
/// </summary>
/// <param name="returnValue"></param>
public delegate void ReturnValuesDelegate(KeyValuePair<int, Dictionary<string,ReturnUnit>> returnValue); public delegate void ReturnValuesDelegate(KeyValuePair<int, Dictionary<string,ReturnUnit>> returnValue);
/// <summary>
/// 返回数据事件
/// </summary>
public event ReturnValuesDelegate ReturnValues; public event ReturnValuesDelegate ReturnValues;
/// <summary>
/// 获取间隔
/// </summary>
private int _getCycle; private int _getCycle;
/// <summary> /// <summary>
@@ -345,13 +358,17 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 将设备指定为未连接
/// </summary>
/// <param name="id">设备的id</param>
public void MoveMachineToUnlinked(int id) public void MoveMachineToUnlinked(int id)
{ {
IEnumerable<BaseMachine> machines; IEnumerable<BaseMachine> machines;
lock(_machines) lock(_machines)
{ {
machines = _machines.Where(c => c.Id == id).ToList(); machines = _machines.Where(c => c.Id == id).ToList();
if (machines.Count() <= 0) return; if (!machines.Any()) return;
_machines.RemoveWhere(p => p.Id == id); _machines.RemoveWhere(p => p.Id == id);
} }
lock(_unlinkedMachines) lock(_unlinkedMachines)
@@ -363,13 +380,17 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 将设备指定为已连接
/// </summary>
/// <param name="id">设备的id</param>
public void MoveMachineToLinked(int id) public void MoveMachineToLinked(int id)
{ {
IEnumerable<BaseMachine> machines; IEnumerable<BaseMachine> machines;
lock (_unlinkedMachines) lock (_unlinkedMachines)
{ {
machines = _unlinkedMachines.Where(c => c.Id == id).ToList(); machines = _unlinkedMachines.Where(c => c.Id == id).ToList();
if (machines.Count() <= 0) return; if (!machines.Any()) return;
_unlinkedMachines.RemoveWhere(p => p.Id == id); _unlinkedMachines.RemoveWhere(p => p.Id == id);
} }
lock (_machines) lock (_machines)
@@ -397,20 +418,32 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 已连接设备更新
/// </summary>
/// <param name="sender"></param>
private void MaintainTasks(object sender) private void MaintainTasks(object sender)
{ {
AsyncHelper.RunSync(MaintainTasksAsync); AsyncHelper.RunSync(MaintainTasksAsync);
} }
/// <summary>
/// 未连接设备更新
/// </summary>
/// <param name="sender"></param>
private void MaintainTasks2(object sender) private void MaintainTasks2(object sender)
{ {
AsyncHelper.RunSync(MaintainTasks2Async); AsyncHelper.RunSync(MaintainTasks2Async);
} }
/// <summary>
/// 已连接设备更新
/// </summary>
/// <returns></returns>
private async Task MaintainTasksAsync() private async Task MaintainTasksAsync()
{ {
HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>(); HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>();
IEnumerable<BaseMachine> saveMachinesEnum = new List<BaseMachine>(); IEnumerable<BaseMachine> saveMachinesEnum;
lock (_machines) lock (_machines)
{ {
saveMachines.UnionWith(_machines); saveMachines.UnionWith(_machines);
@@ -422,6 +455,10 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 未连接设备更新
/// </summary>
/// <returns></returns>
private async Task MaintainTasks2Async() private async Task MaintainTasks2Async()
{ {
HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>(); HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>();
@@ -444,18 +481,28 @@ namespace ModBus.Net
} }
} }
public async Task<bool> SetDatasAsync(string machineToken, MachineSetDataType setDataType, /// <summary>
/// 设置数据
/// </summary>
/// <param name="connectionToken">设备的连接标识</param>
/// <param name="setDataType">设置类型</param>
/// <param name="values">需要设置的数据</param>
/// <returns>是否设置成功</returns>
public async Task<bool> SetDatasAsync(string connectionToken, MachineSetDataType setDataType,
Dictionary<string, double> values) Dictionary<string, double> values)
{ {
BaseMachine machine = null; BaseMachine machine = null;
lock (_machines) lock (_machines)
{ {
machine = _machines.FirstOrDefault(p => p.ConnectionToken == machineToken); machine = _machines.FirstOrDefault(p => p.ConnectionToken == connectionToken);
} }
if (machine == null) return false; if (machine == null) return false;
return await machine.SetDatasAsync(setDataType, values); return await machine.SetDatasAsync(setDataType, values);
} }
/// <summary>
/// 启动TaskManager
/// </summary>
public void TaskStart() public void TaskStart()
{ {
TaskStop(); TaskStop();
@@ -464,6 +511,9 @@ namespace ModBus.Net
GetCycle = TimeRestore.Restore; GetCycle = TimeRestore.Restore;
} }
/// <summary>
/// 停止TaskManager
/// </summary>
public void TaskStop() public void TaskStop()
{ {
lock (_machines) lock (_machines)
@@ -484,6 +534,11 @@ namespace ModBus.Net
} }
} }
/// <summary>
/// 执行对具体设备的数据更新
/// </summary>
/// <param name="machine">设备的实例</param>
/// <returns></returns>
private async Task RunTask(BaseMachine machine) private async Task RunTask(BaseMachine machine)
{ {
try try
@@ -504,10 +559,7 @@ namespace ModBus.Net
{ {
MoveMachineToLinked(machine.Id); MoveMachineToLinked(machine.Id);
} }
if (ReturnValues != null) ReturnValues?.Invoke(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, ans));
{
ReturnValues(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, ans));
}
} }
catch (Exception e) catch (Exception e)
{ {
@@ -515,10 +567,7 @@ namespace ModBus.Net
{ {
MoveMachineToUnlinked(machine.Id); MoveMachineToUnlinked(machine.Id);
} }
if (ReturnValues != null) ReturnValues?.Invoke(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, null));
{
ReturnValues(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, null));
}
} }
} }
} }

View File

@@ -25,7 +25,7 @@ namespace ModBus.Net
/// </summary> /// </summary>
public class TcpConnector : BaseConnector, IDisposable public class TcpConnector : BaseConnector, IDisposable
{ {
public override string ConnectionToken { get { return _host; } } public override string ConnectionToken => _host;
private readonly string _host; private readonly string _host;
@@ -60,13 +60,7 @@ namespace ModBus.Net
TimeoutTime = timeoutTime; TimeoutTime = timeoutTime;
} }
public override bool IsConnected public override bool IsConnected => _socketClient?.Client != null && _socketClient.Connected;
{
get
{
return _socketClient != null && _socketClient.Client != null && _socketClient.Connected;
}
}
public void Dispose() public void Dispose()
{ {

View File

@@ -33,10 +33,7 @@ namespace ModBus.Net
/// <summary> /// <summary>
/// 协议中的内容构造是否小端的,默认是小端构造协议。 /// 协议中的内容构造是否小端的,默认是小端构造协议。
/// </summary> /// </summary>
public static bool LittleEndian public static bool LittleEndian => true;
{
get { return true; }
}
#region Factory #region Factory
@@ -45,17 +42,7 @@ namespace ModBus.Net
/// <summary> /// <summary>
/// ValueHelper单例的实例 /// ValueHelper单例的实例
/// </summary> /// </summary>
public static ValueHelper Instance public static ValueHelper Instance => _Instance ?? (_Instance = new ValueHelper());
{
get
{
if (_Instance == null)
{
_Instance = new ValueHelper();
}
return _Instance;
}
}
#endregion #endregion
@@ -705,22 +692,9 @@ namespace ModBus.Net
} }
protected new bool LittleEndian protected new bool LittleEndian => false;
{
get { return false; }
}
public new static BigEndianValueHelper Instance public new static BigEndianValueHelper Instance => _BigEndianInstance ?? (_BigEndianInstance = new BigEndianValueHelper());
{
get
{
if (_BigEndianInstance == null)
{
_BigEndianInstance = new BigEndianValueHelper();
}
return _BigEndianInstance;
}
}
public override Byte[] GetBytes(short value) public override Byte[] GetBytes(short value)
{ {

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup> </startup>
</configuration> </configuration>

View File

@@ -9,8 +9,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NA200H.UI.ConsoleApp</RootNamespace> <RootNamespace>NA200H.UI.ConsoleApp</RootNamespace>
<AssemblyName>NA200H.UI.ConsoleApp</AssemblyName> <AssemblyName>NA200H.UI.ConsoleApp</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>

View File

@@ -6,6 +6,8 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ModBus.Net; using ModBus.Net;
using System.Reflection; using System.Reflection;
using ModBus.Net.Modbus;
using ModBus.Net.Siemens;
namespace NA200H.UI.ConsoleApp namespace NA200H.UI.ConsoleApp
{ {
@@ -52,9 +54,9 @@ namespace NA200H.UI.ConsoleApp
} }
Console.WriteLine(); Console.WriteLine();
Console.Read(); Console.Read();
Console.Read();*/ Console.Read();
/*
//调用方法二:自动构造 //调用方法二:自动构造
//第一步:先生成一个输入结构体,然后向这个结构体中填写数据 //第一步:先生成一个输入结构体,然后向这个结构体中填写数据
AddressTranslator addressTranslator = new AddressTranslatorNA200H(); AddressTranslator addressTranslator = new AddressTranslatorNA200H();
@@ -119,7 +121,8 @@ namespace NA200H.UI.ConsoleApp
Console.Read(); 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; if (!wrapper.ProtocalLinker.IsConnected) return;
AddressTranslator addressTranslator = new AddressTranslatorSiemens(); AddressTranslator addressTranslator = new AddressTranslatorSiemens();

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup> </startup>
</configuration> </configuration>

View File

@@ -9,10 +9,11 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NA200H.UI.WPF</RootNamespace> <RootNamespace>NA200H.UI.WPF</RootNamespace>
<AssemblyName>NA200H.UI.WPF</AssemblyName> <AssemblyName>NA200H.UI.WPF</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>

View File

@@ -1,15 +1,15 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// 此代码由工具生成。 // 此代码由工具生成。
// 运行时版本: 4.0.30319.34014 // 运行时版本:4.0.30319.42000
// //
// 对此文件的更改可能会导致不正确的行为,并且如果 // 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将丢失。 // 重新生成代码,这些更改将丢失。
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace NA200H.UI.WPF.Properties namespace NA200H.UI.WPF.Properties {
{ using System;
/// <summary> /// <summary>
@@ -22,28 +22,23 @@ namespace NA200H.UI.WPF.Properties
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources internal class Resources {
{
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() internal Resources() {
{
} }
/// <summary> /// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。 /// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager internal static global::System.Resources.ResourceManager ResourceManager {
{ get {
get if (object.ReferenceEquals(resourceMan, null)) {
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NA200H.UI.WPF.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NA200H.UI.WPF.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
@@ -52,18 +47,15 @@ namespace NA200H.UI.WPF.Properties
} }
/// <summary> /// <summary>
/// 为所有资源查找重写当前线程的 CurrentUICulture 属性, /// 使用此强类型资源类,为所有资源查找
/// 方法是使用此强类型资源类 /// 重写当前线程的 CurrentUICulture 属性
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture internal static global::System.Globalization.CultureInfo Culture {
{ get {
get
{
return resourceCulture; return resourceCulture;
} }
set set {
{
resourceCulture = value; resourceCulture = value;
} }
} }

View File

@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// 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. // 重新生成代码,这些更改将会丢失。
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace NA200H.UI.WPF.Properties namespace NA200H.UI.WPF.Properties {
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default public static Settings Default {
{ get {
get
{
return defaultInstance; return defaultInstance;
} }
} }

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup> </startup>
</configuration> </configuration>

View File

@@ -30,13 +30,13 @@ namespace Siemens_S7_200.UI.WPF.TaskTest
//增加需要通信的PLC地址 //增加需要通信的PLC地址
List<AddressUnit> addressUnits = new List<AddressUnit> List<AddressUnit> addressUnits = new List<AddressUnit>
{ {
new AddressUnit() {Id = 0, Area = "V", Address = 0, CommunicationTag = "D1", DataType = typeof (ushort), Zoom = 1}, new AddressUnit() {Id = 0, Area = "V", Address = 1, 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 = 1, Area = "V", Address = 3, CommunicationTag = "D2", DataType = typeof (float), Zoom = 1}
}; };
//初始化任务管理器 //初始化任务管理器
TaskManager task = new TaskManager(300, true); 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)); true));
//增加值返回时的处理函数 //增加值返回时的处理函数
task.ReturnValues += (returnValues) => task.ReturnValues += (returnValues) =>
@@ -45,12 +45,12 @@ namespace Siemens_S7_200.UI.WPF.TaskTest
value = new List<string>(); value = new List<string>();
if (returnValues.Value != null) 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); siemensItems.Dispatcher.Invoke(() => siemensItems.ItemsSource = value);
} }
else else
{ {
Console.WriteLine(String.Format("ip {0} not return value", returnValues.Key)); Console.WriteLine($"ip {returnValues.Key} not return value");
} }
}; };
//启动任务 //启动任务

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Siemens_S7_200.UI.WPF.TaskTest</RootNamespace> <RootNamespace>Siemens_S7_200.UI.WPF.TaskTest</RootNamespace>
<AssemblyName>Siemens_S7_200.UI.WPF.TaskTest</AssemblyName> <AssemblyName>Siemens_S7_200.UI.WPF.TaskTest</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>

View File

@@ -19,7 +19,7 @@ Table of Content:
* Siemens Tcp protocal (acturally it is the same as Profinet) * Siemens Tcp protocal (acturally it is the same as Profinet)
* All communications can be asyncronized. * All communications can be asyncronized.
* A task manager that you can easily manage multiple connections. * 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.
##<a name="usage"></a> Usage ##<a name="usage"></a> Usage