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:
@@ -13,13 +13,15 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CrossLampControl.WebApi</RootNamespace>
|
||||
<AssemblyName>CrossLampControl.WebApi</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<MvcBuildViews>false</MvcBuildViews>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<TargetFrameworkProfile />
|
||||
<UseGlobalApplicationHostFile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -42,13 +44,13 @@
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web.DynamicData" />
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Abstractions" />
|
||||
<Reference Include="System.Web.Routing" />
|
||||
@@ -102,6 +104,7 @@
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="WebGrease">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\WebGrease.1.5.2\lib\WebGrease.dll</HintPath>
|
||||
|
||||
@@ -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
|
||||
http://go.microsoft.com/fwlink/?LinkId=301879
|
||||
@@ -11,10 +11,18 @@
|
||||
<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"/>
|
||||
</connectionStrings>
|
||||
<appSettings></appSettings>
|
||||
<appSettings/>
|
||||
<!--
|
||||
有关 web.config 更改的说明,请参见 http://go.microsoft.com/fwlink/?LinkId=235367。
|
||||
|
||||
可在 <httpRuntime> 标记上设置以下特性。
|
||||
<system.Web>
|
||||
<httpRuntime targetFramework="4.6" />
|
||||
</system.Web>
|
||||
-->
|
||||
<system.web>
|
||||
<authentication mode="None"/>
|
||||
<compilation debug="true" targetFramework="4.5" />
|
||||
<compilation debug="true" targetFramework="4.6"/>
|
||||
<httpRuntime targetFramework="4.5"/>
|
||||
</system.web>
|
||||
<system.webServer>
|
||||
|
||||
@@ -4,11 +4,22 @@ using System.Linq;
|
||||
|
||||
namespace ModBus.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯
|
||||
/// </summary>
|
||||
public abstract class AddressCombiner
|
||||
{
|
||||
/// <summary>
|
||||
/// 组合地址
|
||||
/// </summary>
|
||||
/// <param name="addresses">需要进行组合的地址</param>
|
||||
/// <returns>组合完成后与设备通讯的地址</returns>
|
||||
public abstract IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连续的地址将组合成一组,向设备进行通讯
|
||||
/// </summary>
|
||||
public class AddressCombinerContinus : AddressCombiner
|
||||
{
|
||||
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
||||
|
||||
@@ -2,11 +2,23 @@
|
||||
|
||||
namespace ModBus.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 地址编码器
|
||||
/// </summary>
|
||||
public abstract class AddressFormater
|
||||
{
|
||||
/// <summary>
|
||||
/// 编码地址
|
||||
/// </summary>
|
||||
/// <param name="area">地址所在的数据区域</param>
|
||||
/// <param name="address">地址</param>
|
||||
/// <returns>编码后的地址</returns>
|
||||
public abstract string FormatAddress(string area, int address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基本的地址编码器
|
||||
/// </summary>
|
||||
public class AddressFormaterBase : AddressFormater
|
||||
{
|
||||
public override string FormatAddress(string area, int address)
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
namespace ModBus.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据单元翻译器
|
||||
/// 地址翻译器
|
||||
/// </summary>
|
||||
public abstract class AddressTranslator
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace ModBus.Net
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基本的单元转换器
|
||||
/// 基本的地址翻译器
|
||||
/// </summary>
|
||||
public class AddressTranslatorBase : AddressTranslator
|
||||
{
|
||||
|
||||
@@ -13,6 +13,12 @@ namespace ModBus.Net
|
||||
TaskContinuationOptions.None,
|
||||
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)
|
||||
{
|
||||
return AsyncHelper._myTaskFactory
|
||||
@@ -22,6 +28,10 @@ namespace ModBus.Net
|
||||
.GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run async method syncronized.
|
||||
/// </summary>
|
||||
/// <param name="func">Async method</param>
|
||||
public static void RunSync(Func<Task> func)
|
||||
{
|
||||
AsyncHelper._myTaskFactory
|
||||
@@ -31,6 +41,12 @@ namespace ModBus.Net
|
||||
.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,
|
||||
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>
|
||||
public class AsyncLock
|
||||
{
|
||||
@@ -58,6 +74,10 @@ namespace ModBus.Net
|
||||
_releaser = Task.FromResult(new Releaser(this));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lock the async method. Call like: using (await asynclock.LockAsync())
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<Releaser> LockAsync()
|
||||
{
|
||||
var wait = _semaphore.WaitAsync();
|
||||
@@ -88,6 +108,9 @@ namespace ModBus.Net
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AsyncSemaphore semaphore the multi run tasks.
|
||||
/// </summary>
|
||||
public class AsyncSemaphore
|
||||
{
|
||||
private readonly static Task _completed = Task.FromResult(true);
|
||||
|
||||
@@ -5,6 +5,9 @@ namespace ModBus.Net
|
||||
{
|
||||
public abstract class BaseConnector
|
||||
{
|
||||
/// <summary>
|
||||
/// 标识Connector的连接关键字
|
||||
/// </summary>
|
||||
public abstract string ConnectionToken { get; }
|
||||
/// <summary>
|
||||
/// 是否处于连接状态
|
||||
@@ -13,41 +16,41 @@ namespace ModBus.Net
|
||||
/// <summary>
|
||||
/// 连接PLC
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public abstract bool Connect();
|
||||
/// <summary>
|
||||
/// 连接PLC,异步
|
||||
/// </summary>
|
||||
/// /// <returns></returns>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public abstract Task<bool> ConnectAsync();
|
||||
/// <summary>
|
||||
/// 断开PLC
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <returns>是否断开成功</returns>
|
||||
public abstract bool Disconnect();
|
||||
/// <summary>
|
||||
/// 无返回发送数据
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">需要发送的数据</param>
|
||||
/// <returns>是否发送成功</returns>
|
||||
public abstract bool SendMsgWithoutReturn(byte[] message);
|
||||
/// <summary>
|
||||
/// 无返回发送数据,异步
|
||||
/// 无返回发送数据
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">需要发送的数据</param>
|
||||
/// <returns>是否发送成功</returns>
|
||||
public abstract Task<bool> SendMsgWithoutReturnAsync(byte[] message);
|
||||
/// <summary>
|
||||
/// 带返回发送数据
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">需要发送的数据</param>
|
||||
/// <returns>是否发送成功</returns>
|
||||
public abstract byte[] SendMsg(byte[] message);
|
||||
/// <summary>
|
||||
/// 带返回发送数据,异步
|
||||
/// 带返回发送数据
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">需要发送的数据</param>
|
||||
/// <returns>是否发送成功</returns>
|
||||
public abstract Task<byte[]> SendMsgAsync(byte[] message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,84 +5,136 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace ModBus.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 向设备设置值的方式
|
||||
/// </summary>
|
||||
public enum MachineSetDataType
|
||||
{
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
Address,
|
||||
/// <summary>
|
||||
/// 通讯标识
|
||||
/// </summary>
|
||||
CommunicationTag
|
||||
}
|
||||
|
||||
public abstract class BaseMachine : IMachineProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备的Id
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备所在工程的名称
|
||||
/// </summary>
|
||||
public string ProjectName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备的名称
|
||||
/// </summary>
|
||||
public string MachineName { get; set; }
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
return BaseUtility.IsConnected;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否处于连接状态
|
||||
/// </summary>
|
||||
public bool IsConnected => BaseUtility.IsConnected;
|
||||
|
||||
public string ConnectionToken
|
||||
{
|
||||
get { return BaseUtility.ConnectionToken; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 标识设备的连接关键字
|
||||
/// </summary>
|
||||
public string ConnectionToken => BaseUtility.ConnectionToken;
|
||||
|
||||
/// <summary>
|
||||
/// 地址编码器
|
||||
/// </summary>
|
||||
public AddressFormater AddressFormater { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地址解码器
|
||||
/// </summary>
|
||||
public AddressCombiner AddressCombiner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地址转换器
|
||||
/// </summary>
|
||||
public AddressTranslator AddressTranslator
|
||||
{
|
||||
get { return BaseUtility.AddressTranslator; }
|
||||
set { BaseUtility.AddressTranslator = value; }
|
||||
}
|
||||
|
||||
public MachineExtend MachineExtend { get; set; }
|
||||
|
||||
protected IEnumerable<CommunicationUnit> CommunicateAddresses
|
||||
{
|
||||
get { return AddressCombiner.Combine(GetAddresses); }
|
||||
}
|
||||
/// <summary>
|
||||
/// 与设备实际通讯的连续地址
|
||||
/// </summary>
|
||||
protected IEnumerable<CommunicationUnit> CommunicateAddresses => AddressCombiner.Combine(GetAddresses);
|
||||
|
||||
/// <summary>
|
||||
/// 描述需要与设备通讯的地址
|
||||
/// </summary>
|
||||
public IEnumerable<AddressUnit> GetAddresses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否保持连接
|
||||
/// </summary>
|
||||
public bool KeepConnect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备的连接器
|
||||
/// </summary>
|
||||
protected BaseUtility BaseUtility { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// </summary>
|
||||
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
||||
protected BaseMachine(IEnumerable<AddressUnit> getAddresses)
|
||||
: this(getAddresses, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// </summary>
|
||||
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
||||
/// <param name="keepConnect">是否保持连接</param>
|
||||
protected BaseMachine(IEnumerable<AddressUnit> getAddresses, bool keepConnect)
|
||||
{
|
||||
GetAddresses = getAddresses;
|
||||
KeepConnect = keepConnect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取数据
|
||||
/// </summary>
|
||||
/// <returns>从设备读取的数据</returns>
|
||||
public Dictionary<string, ReturnUnit> GetDatas()
|
||||
{
|
||||
return AsyncHelper.RunSync(GetDatasAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取数据
|
||||
/// </summary>
|
||||
/// <returns>从设备读取的数据</returns>
|
||||
public async Task<Dictionary<string,ReturnUnit>> GetDatasAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dictionary<string, ReturnUnit> ans = new Dictionary<string, ReturnUnit>();
|
||||
//检测并连接设备
|
||||
if (!BaseUtility.IsConnected)
|
||||
{
|
||||
await BaseUtility.ConnectAsync();
|
||||
}
|
||||
//如果无法连接,终止
|
||||
if (!BaseUtility.IsConnected) return null;
|
||||
//遍历每一个实际向设备获取数据的连续地址
|
||||
foreach (var communicateAddress in CommunicateAddresses)
|
||||
{
|
||||
//获取数据
|
||||
var datas =
|
||||
await
|
||||
BaseUtility.GetDatasAsync<byte>(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,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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
//检测并连接设备
|
||||
if (!BaseUtility.IsConnected)
|
||||
{
|
||||
await BaseUtility.ConnectAsync();
|
||||
}
|
||||
//如果设备无法连接,终止
|
||||
if (!BaseUtility.IsConnected) return false;
|
||||
List<AddressUnit> addresses = new List<AddressUnit>();
|
||||
//遍历每个要设置的值
|
||||
foreach (var value in values)
|
||||
{
|
||||
//根据设置类型找到对应的地址描述
|
||||
AddressUnit address = null;
|
||||
switch (setDataType)
|
||||
{
|
||||
@@ -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<object> datasList = new List<object>();
|
||||
//需要设置的字节数,计数
|
||||
var setCount = (int)
|
||||
Math.Ceiling(communicateAddress.GetCount*
|
||||
BigEndianValueHelper.Instance.ByteLength[
|
||||
communicateAddress.DataType.FullName]);
|
||||
//总数
|
||||
var allBytes = setCount;
|
||||
//编码开始地址
|
||||
var addressStart = AddressFormater.FormatAddress(communicateAddress.Area,
|
||||
communicateAddress.Address);
|
||||
while (setCount > 0)
|
||||
{
|
||||
//编码当前地址
|
||||
var address = AddressFormater.FormatAddress(communicateAddress.Area,
|
||||
communicateAddress.Address + allBytes - setCount);
|
||||
//找到对应的描述地址
|
||||
var addressUnit =
|
||||
GetAddresses.SingleOrDefault(
|
||||
p =>
|
||||
p.Area == communicateAddress.Area &&
|
||||
p.Address == communicateAddress.Address + allBytes - setCount);
|
||||
//如果没有相应地址,跳过
|
||||
if (addressUnit == null) continue;
|
||||
//获取写入类型
|
||||
Type dataType = addressUnit.DataType;
|
||||
switch (setDataType)
|
||||
{
|
||||
case MachineSetDataType.Address:
|
||||
{
|
||||
//获取要写入的值
|
||||
var value = values.SingleOrDefault(p => p.Key == address);
|
||||
//将要写入的值加入队列
|
||||
datasList.Add(Convert.ChangeType(value.Value, dataType));
|
||||
break;
|
||||
}
|
||||
@@ -204,7 +290,7 @@ namespace ModBus.Net
|
||||
}
|
||||
setCount -= (int) BigEndianValueHelper.Instance.ByteLength[dataType.FullName];
|
||||
}
|
||||
|
||||
//写入数据
|
||||
await BaseUtility.SetDatasAsync(2, 0, addressStart, datasList.ToArray());
|
||||
}
|
||||
}
|
||||
@@ -216,23 +302,41 @@ namespace ModBus.Net
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备
|
||||
/// </summary>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public bool Connect()
|
||||
{
|
||||
return BaseUtility.Connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备
|
||||
/// </summary>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public async Task<bool> ConnectAsync()
|
||||
{
|
||||
return await BaseUtility.ConnectAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开设备
|
||||
/// </summary>
|
||||
/// <returns>是否断开成功</returns>
|
||||
public bool Disconnect()
|
||||
{
|
||||
return BaseUtility.Disconnect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将获取的数据转换成可以向设备写入的数据格式
|
||||
/// </summary>
|
||||
/// <param name="getValues">获取的数据</param>
|
||||
/// <returns>写入的数据</returns>
|
||||
public static Dictionary<string, double> MapGetValuesToSetValues(Dictionary<string, ReturnUnit> getValues)
|
||||
{
|
||||
if (getValues == null) return null;
|
||||
return (from getValue in getValues
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 区域
|
||||
/// </summary>
|
||||
public string Area { get; set; }
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
public int Address { get; set; }
|
||||
/// <summary>
|
||||
/// 获取个数
|
||||
/// </summary>
|
||||
public int GetCount { get; set; }
|
||||
/// <summary>
|
||||
/// 数据类型
|
||||
/// </summary>
|
||||
public Type DataType { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据单元扩展,返回数据时会同时将其返回
|
||||
/// </summary>
|
||||
public class UnitExtend
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class MachineExtend
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回的数据单元
|
||||
/// </summary>
|
||||
public class ReturnUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回的数据
|
||||
/// </summary>
|
||||
public double PlcValue { get; set; }
|
||||
/// <summary>
|
||||
/// 数据的扩展
|
||||
/// </summary>
|
||||
public UnitExtend UnitExtend { get; set; }
|
||||
}
|
||||
|
||||
public class AddressUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据单元Id
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// 数据所属的区域,Modbus指通讯码,PROFINET指数据块
|
||||
/// 数据所属的区域
|
||||
/// </summary>
|
||||
public string Area { get; set; }
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
public int Address { get; set; }
|
||||
/// <summary>
|
||||
/// 数据类型
|
||||
/// </summary>
|
||||
public Type DataType { get; set; }
|
||||
/// <summary>
|
||||
/// 放缩比例
|
||||
/// </summary>
|
||||
public double Zoom { get; set; }
|
||||
/// <summary>
|
||||
/// 小数位数
|
||||
/// </summary>
|
||||
public int DecimalPos { get; set; }
|
||||
/// <summary>
|
||||
/// 通讯标识名称
|
||||
/// </summary>
|
||||
public string CommunicationTag { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
public string Unit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 扩展
|
||||
/// </summary>
|
||||
public UnitExtend UnitExtend { get; set; }
|
||||
}
|
||||
|
||||
@@ -312,11 +458,26 @@ namespace ModBus.Net
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备的抽象
|
||||
/// </summary>
|
||||
public interface IMachineProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
int Id { get; set; }
|
||||
/// <summary>
|
||||
/// 工程名
|
||||
/// </summary>
|
||||
string ProjectName { get; set; }
|
||||
/// <summary>
|
||||
/// 设备名
|
||||
/// </summary>
|
||||
string MachineName { get; set; }
|
||||
/// <summary>
|
||||
/// 标识设备的连接关键字
|
||||
/// </summary>
|
||||
string ConnectionToken { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,13 @@ namespace ModBus.Net
|
||||
public abstract class BaseProtocal
|
||||
{
|
||||
/// <summary>
|
||||
/// 发送数据
|
||||
/// 协议的连接器
|
||||
/// </summary>
|
||||
/// <param name="content">需要发送的数据</param>
|
||||
/// <returns>数据是否正确接收</returns>
|
||||
public ProtocalLinker ProtocalLinker { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// </summary>
|
||||
protected BaseProtocal()
|
||||
{
|
||||
Protocals = new Dictionary<string, ProtocalUnit>();
|
||||
@@ -25,8 +26,8 @@ namespace ModBus.Net
|
||||
/// <summary>
|
||||
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
|
||||
/// </summary>
|
||||
/// <param name="protocalName">协议的类的名称</param>
|
||||
/// <returns></returns>
|
||||
/// <param name="type">协议的类的GetType</param>
|
||||
/// <returns>协议的实例</returns>
|
||||
public ProtocalUnit this[Type type]
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (linkProtocal == null) return;
|
||||
@@ -56,71 +64,59 @@ namespace ModBus.Net
|
||||
/// <summary>
|
||||
/// 发送协议内容并接收,一般方法
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="content">写入的内容,使用对象数组描述</param>
|
||||
/// <returns>从设备获取的字节流</returns>
|
||||
public virtual byte[] SendReceive(params object[] content)
|
||||
{
|
||||
return AsyncHelper.RunSync(() => SendReceiveAsync(content));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送协议内容并接收,一般方法(异步)
|
||||
/// 发送协议内容并接收,一般方法
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="content">写入的内容,使用对象数组描述</param>
|
||||
/// <returns>从设备获取的字节流</returns>
|
||||
public virtual async Task<byte[]> SendReceiveAsync(params object[] content)
|
||||
{
|
||||
if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
|
||||
{
|
||||
await ConnectAsync();
|
||||
}
|
||||
if (ProtocalLinker != null)
|
||||
{
|
||||
return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(content));
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
||||
/// </summary>
|
||||
/// <param name="unit"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="unit">协议的实例</param>
|
||||
/// <param name="content">输入信息的结构化描述</param>
|
||||
/// <returns>输出信息的结构化描述</returns>
|
||||
public virtual OutputStruct SendReceive(ProtocalUnit unit, InputStruct content)
|
||||
{
|
||||
int t = 0;
|
||||
//如果为特别处理协议的话,跳过协议扩展收缩
|
||||
var formatContent = unit.Format(content);
|
||||
if (formatContent != null)
|
||||
{
|
||||
byte[] receiveContent;
|
||||
if (unit is SpecialProtocalUnit)
|
||||
{
|
||||
receiveContent = ProtocalLinker.SendReceiveWithoutExtAndDec(formatContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
receiveContent = ProtocalLinker.SendReceive(formatContent);
|
||||
}
|
||||
if (receiveContent != null)
|
||||
{
|
||||
return unit.Unformat(receiveContent, ref t);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送协议,通过传入需要使用的协议内容和输入结构(异步)
|
||||
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
||||
/// </summary>
|
||||
/// <param name="unit"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="unit">协议的实例</param>
|
||||
/// <param name="content">输入信息的结构化描述</param>
|
||||
/// <returns>输出信息的结构化描述</returns>
|
||||
public virtual async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
||||
{
|
||||
int t = 0;
|
||||
//如果为特别处理协议的话,跳过协议扩展收缩
|
||||
var formatContent = unit.Format(content);
|
||||
if (formatContent != null)
|
||||
{
|
||||
byte[] receiveContent;
|
||||
//如果为特别处理协议的话,跳过协议扩展收缩
|
||||
if (unit is SpecialProtocalUnit)
|
||||
{
|
||||
receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ModBus.Net
|
||||
@@ -12,26 +13,29 @@ namespace ModBus.Net
|
||||
protected BaseProtocal Wrapper;
|
||||
protected string ConnectionString { get; set; }
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Wrapper == null || Wrapper.ProtocalLinker == null) return false;
|
||||
return Wrapper.ProtocalLinker.IsConnected;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设备是否已经连接
|
||||
/// </summary>
|
||||
public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected;
|
||||
|
||||
public string ConnectionToken
|
||||
{
|
||||
get { return Wrapper.ProtocalLinker.ConnectionToken; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 标识设备的连接关键字
|
||||
/// </summary>
|
||||
public string ConnectionToken => Wrapper.ProtocalLinker.ConnectionToken;
|
||||
|
||||
/// <summary>
|
||||
/// 地址翻译器
|
||||
/// </summary>
|
||||
public AddressTranslator AddressTranslator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// </summary>
|
||||
protected BaseUtility()
|
||||
{
|
||||
AddressTranslator = new AddressTranslatorBase();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置连接类型
|
||||
/// </summary>
|
||||
@@ -44,7 +48,7 @@ namespace ModBus.Net
|
||||
/// <param name="belongAddress">从站地址</param>
|
||||
/// <param name="masterAddress">主站地址</param>
|
||||
/// <param name="startAddress">开始地址</param>
|
||||
/// <param name="getByteCount">获取类型和个数</param>
|
||||
/// <param name="getByteCount">获取字节数个数</param>
|
||||
/// <returns>接收到的byte数据</returns>
|
||||
protected virtual byte[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount)
|
||||
{
|
||||
@@ -52,32 +56,37 @@ namespace ModBus.Net
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据(异步)
|
||||
/// 获取数据
|
||||
/// </summary>
|
||||
/// <param name="belongAddress">从站地址</param>
|
||||
/// <param name="masterAddress">主站地址</param>
|
||||
/// <param name="startAddress">开始地址</param>
|
||||
/// <param name="getByteCount">获取类型和个数</param>
|
||||
/// <param name="getByteCount">获取字节数个数</param>
|
||||
/// <returns>接收到的byte数据</returns>
|
||||
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,
|
||||
KeyValuePair<Type, int> getTypeAndCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
string typeName = getTypeAndCount.Key.FullName;
|
||||
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
|
||||
byte[] getBytes = GetDatas(belongAddress, masterAddress, startAddress,
|
||||
(int) Math.Ceiling(bCount*getTypeAndCount.Value));
|
||||
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getTypeAndCount));
|
||||
}
|
||||
|
||||
/// <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,
|
||||
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,
|
||||
int getByteCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
var getBytes = GetDatas(belongAddress, masterAddress, startAddress,
|
||||
new KeyValuePair<Type, int>(typeof (T), getByteCount));
|
||||
return BigEndianValueHelper.Instance.ObjectArrayToDestinationArray<T>(getBytes);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return AsyncHelper.RunSync(() => GetDatasAsync<T>(belongAddress, masterAddress, startAddress, getByteCount));
|
||||
}
|
||||
|
||||
/// <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,
|
||||
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,
|
||||
IEnumerable<KeyValuePair<Type, int>> getTypeAndCountList)
|
||||
{
|
||||
try
|
||||
{
|
||||
int bAllCount = 0;
|
||||
foreach (var getTypeAndCount in getTypeAndCountList)
|
||||
{
|
||||
string typeName = getTypeAndCount.Key.FullName;
|
||||
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
|
||||
bAllCount += (int)Math.Ceiling(bCount * getTypeAndCount.Value);
|
||||
}
|
||||
byte[] getBytes = GetDatas(belongAddress, masterAddress, startAddress, bAllCount);
|
||||
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCountList);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return
|
||||
AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getTypeAndCountList));
|
||||
}
|
||||
|
||||
/// <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,
|
||||
IEnumerable<KeyValuePair<Type, int>> getTypeAndCountList)
|
||||
{
|
||||
try
|
||||
{
|
||||
int bAllCount = 0;
|
||||
foreach (var getTypeAndCount in getTypeAndCountList)
|
||||
{
|
||||
string typeName = getTypeAndCount.Key.FullName;
|
||||
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
|
||||
bAllCount += (int)Math.Ceiling(bCount * getTypeAndCount.Value);
|
||||
}
|
||||
var translateTypeAndCount = getTypeAndCountList as IList<KeyValuePair<Type, int>> ??
|
||||
getTypeAndCountList.ToList();
|
||||
int bAllCount = (
|
||||
from getTypeAndCount in translateTypeAndCount
|
||||
let typeName = getTypeAndCount.Key.FullName
|
||||
let bCount = BigEndianValueHelper.Instance.ByteLength[typeName]
|
||||
select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum();
|
||||
byte[] getBytes = await GetDatasAsync(belongAddress, masterAddress, startAddress, bAllCount);
|
||||
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCountList);
|
||||
return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -181,7 +200,7 @@ namespace ModBus.Net
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置数据(异步)
|
||||
/// 设置数据
|
||||
/// </summary>
|
||||
/// <param name="belongAddress">从站地址</param>
|
||||
/// <param name="masterAddress">主站地址</param>
|
||||
@@ -207,16 +226,28 @@ namespace ModBus.Net
|
||||
public abstract bool SetTime(byte belongAddress, DateTime setTime);
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备
|
||||
/// </summary>
|
||||
/// <returns>设备是否连接成功</returns>
|
||||
public bool Connect()
|
||||
{
|
||||
return Wrapper.Connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备
|
||||
/// </summary>
|
||||
/// <returns>设备是否连接成功</returns>
|
||||
public async Task<bool> ConnectAsync()
|
||||
{
|
||||
return await Wrapper.ConnectAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开设备
|
||||
/// </summary>
|
||||
/// <returns>设备是否断开成功</returns>
|
||||
public bool Disconnect()
|
||||
{
|
||||
return Wrapper.Disconnect();
|
||||
|
||||
@@ -38,35 +38,17 @@ namespace ModBus.Net.FBox
|
||||
}
|
||||
}
|
||||
|
||||
public string AuthorizeEndpoint
|
||||
{
|
||||
get { return BaseAddress + "/connect/authorize"; }
|
||||
}
|
||||
public string AuthorizeEndpoint => BaseAddress + "/connect/authorize";
|
||||
|
||||
public string LogoutEndpoint
|
||||
{
|
||||
get { return BaseAddress + "/connect/endsession"; }
|
||||
}
|
||||
public string LogoutEndpoint => BaseAddress + "/connect/endsession";
|
||||
|
||||
public string TokenEndpoint
|
||||
{
|
||||
get { return BaseAddress + "/connect/token"; }
|
||||
}
|
||||
public string TokenEndpoint => BaseAddress + "/connect/token";
|
||||
|
||||
public string UserInfoEndpoint
|
||||
{
|
||||
get {return BaseAddress + "/connect/userinfo"; }
|
||||
}
|
||||
public string UserInfoEndpoint => BaseAddress + "/connect/userinfo";
|
||||
|
||||
public string IdentityTokenValidationEndpoint
|
||||
{
|
||||
get {return BaseAddress + "/connect/identitytokenvalidation"; }
|
||||
}
|
||||
public string IdentityTokenValidationEndpoint => BaseAddress + "/connect/identitytokenvalidation";
|
||||
|
||||
public string TokenRevocationEndpoint
|
||||
{
|
||||
get {return BaseAddress + "/connect/revocation"; }
|
||||
}
|
||||
public string TokenRevocationEndpoint => BaseAddress + "/connect/revocation";
|
||||
|
||||
public string AspNetWebApiSampleApi
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DelinRemoteControlBoxTest
|
||||
namespace ModBus.Net.FBox
|
||||
{
|
||||
public class BoxGroup
|
||||
{
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace ModBus.Net.FBox
|
||||
{
|
||||
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();
|
||||
AddressCombiner = new AddressCombinerFBox();
|
||||
|
||||
@@ -66,9 +66,9 @@ namespace ModBus.Net.FBox
|
||||
{
|
||||
var readRequestFBoxInputStruct = new ReadRequestFBoxInputStruct(startAddress, (ushort)getByteCount, AddressTranslator);
|
||||
var readRequestSiemensOutputStruct =
|
||||
(ReadRequestFBoxOutputStruct)await
|
||||
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestFBoxProtocal)], readRequestFBoxInputStruct);
|
||||
return readRequestSiemensOutputStruct.GetValue;
|
||||
await
|
||||
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestFBoxProtocal)], readRequestFBoxInputStruct) as ReadRequestFBoxOutputStruct;
|
||||
return readRequestSiemensOutputStruct?.GetValue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DelinRemoteControlBoxTest;
|
||||
using Microsoft.AspNet.SignalR.Client;
|
||||
using Newtonsoft.Json;
|
||||
using Thinktecture.IdentityModel.Client;
|
||||
@@ -45,36 +44,18 @@ namespace ModBus.Net.FBox
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
private string MachineId
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConnectionToken.Split(',')[0];
|
||||
}
|
||||
}
|
||||
private string MachineId => ConnectionToken.Split(',')[0];
|
||||
|
||||
private string LocalSequence {
|
||||
get
|
||||
{
|
||||
return ConnectionToken.Split(',')[1];
|
||||
}
|
||||
}
|
||||
private string LocalSequence => ConnectionToken.Split(',')[1];
|
||||
|
||||
private static readonly AsyncLock _lock = new AsyncLock();
|
||||
|
||||
private bool _connected;
|
||||
public override bool IsConnected { get { return _connected; } }
|
||||
public override bool IsConnected => _connected;
|
||||
private SignalRSigninMsg Msg { get; set;}
|
||||
|
||||
private Constants _constants;
|
||||
private Constants Constants
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_constants == null) _constants = new Constants();
|
||||
return _constants;
|
||||
}
|
||||
}
|
||||
private Constants Constants => _constants ?? (_constants = new Constants());
|
||||
|
||||
public SignalRConnector(string machineId, string localSequence, SignalRSigninMsg msg)
|
||||
{
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
/// <summary>
|
||||
/// 从输入结构格式化
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">结构化的输入数据</param>
|
||||
/// <returns>格式化后的字节流</returns>
|
||||
byte[] Format(InputStruct message);
|
||||
|
||||
/// <summary>
|
||||
/// 从对象的参数数组格式化
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">非结构化的输入数据</param>
|
||||
/// <returns>格式化后的字节流</returns>
|
||||
byte[] Format(params object[] message);
|
||||
|
||||
/// <summary>
|
||||
/// 把仪器返回的内容填充到输出结构中
|
||||
/// </summary>
|
||||
/// <param name="messageBytes"></param>
|
||||
/// <param name="pos"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="messageBytes">返回数据的字节流</param>
|
||||
/// <param name="pos">转换标记位</param>
|
||||
/// <returns>结构化的输出数据</returns>
|
||||
OutputStruct Unformat(byte[] messageBytes, ref int pos);
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,9 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ModBus.Net</RootNamespace>
|
||||
<AssemblyName>ModBus.Net</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
||||
@@ -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 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;
|
||||
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;
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设备是否连接
|
||||
/// </summary>
|
||||
public bool IsConnected => _baseConnector != null && _baseConnector.IsConnected;
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备
|
||||
/// </summary>
|
||||
/// <returns>设备是否连接成功</returns>
|
||||
public bool Connect()
|
||||
{
|
||||
return _baseConnector.Connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备
|
||||
/// </summary>
|
||||
/// <returns>设备是否连接成功</returns>
|
||||
public async Task<bool> ConnectAsync()
|
||||
{
|
||||
return await _baseConnector.ConnectAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开设备
|
||||
/// </summary>
|
||||
/// <returns>设备是否断开成功</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -94,13 +97,10 @@ namespace ModBus.Net
|
||||
/// <returns>协议是否是正确的</returns>
|
||||
public virtual bool CheckRight(byte[] content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
if (content != null) return true;
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协议内容扩展,发送时根据需要扩展
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,35 +5,35 @@ namespace ModBus.Net
|
||||
public abstract class ProtocalUnit : IProtocalFormatting
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化,将输入结构转换为字节数组
|
||||
/// 从输入结构格式化
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">结构化的输入数据</param>
|
||||
/// <returns>格式化后的字节流</returns>
|
||||
public abstract byte[] Format(InputStruct message);
|
||||
|
||||
/// <summary>
|
||||
/// 格式化,将对象数组转换为字节数组
|
||||
/// 从对象的参数数组格式化
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="message">非结构化的输入数据</param>
|
||||
/// <returns>格式化后的字节流</returns>
|
||||
public virtual byte[] Format(params object[] message)
|
||||
{
|
||||
return TranslateContent(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结构化,将字节数组转换为输出结构。
|
||||
/// 把仪器返回的内容填充到输出结构中
|
||||
/// </summary>
|
||||
/// <param name="messageBytes"></param>
|
||||
/// <param name="pos"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="messageBytes">返回数据的字节流</param>
|
||||
/// <param name="pos">转换标记位</param>
|
||||
/// <returns>结构化的输出数据</returns>
|
||||
public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos);
|
||||
|
||||
/// <summary>
|
||||
/// 转换静态方法,把对象数组转换为字节数组。
|
||||
/// </summary>
|
||||
/// <param name="contents"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="contents">对象数组</param>
|
||||
/// <returns>字节数组</returns>
|
||||
public static byte[] TranslateContent(params object[] contents)
|
||||
{
|
||||
return BigEndianValueHelper.Instance.ObjectArrayToByteArray(contents);
|
||||
|
||||
@@ -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,13 +51,10 @@ namespace ModBus.Net.Siemens
|
||||
|
||||
public override async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
||||
{
|
||||
if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
|
||||
{
|
||||
if (connectTryCount > 10) return null;
|
||||
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);
|
||||
}
|
||||
return await base.SendReceiveAsync(unit, content);
|
||||
}
|
||||
|
||||
private async Task<OutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
||||
{
|
||||
@@ -71,11 +68,10 @@ namespace ModBus.Net.Siemens
|
||||
|
||||
public override async Task<bool> ConnectAsync()
|
||||
{
|
||||
connectTryCount++;
|
||||
_connectTryCount++;
|
||||
ProtocalLinker = new SiemensTcpProtocalLinker(_ip);
|
||||
if (await ProtocalLinker.ConnectAsync())
|
||||
{
|
||||
connectTryCount = 0;
|
||||
if (!await ProtocalLinker.ConnectAsync()) return false;
|
||||
_connectTryCount = 0;
|
||||
var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst);
|
||||
return
|
||||
await await
|
||||
@@ -91,10 +87,8 @@ namespace ModBus.Net.Siemens
|
||||
await
|
||||
SendReceiveAsync(this[typeof (EstablishAssociationSiemensProtocal)],
|
||||
inputStruct2);
|
||||
return true;
|
||||
return outputStruct2 != null;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace ModBus.Net
|
||||
/// </summary>
|
||||
private HashSet<BaseMachine> _unlinkedMachines;
|
||||
//private TaskFactory<Dictionary<string,ReturnUnit>> _tasks;
|
||||
private TaskScheduler _scheduler;
|
||||
//private TaskScheduler _scheduler;
|
||||
//private CancellationTokenSource _cts;
|
||||
|
||||
/// <summary>
|
||||
@@ -186,6 +186,9 @@ namespace ModBus.Net
|
||||
/// </summary>
|
||||
private Timer _timer2;
|
||||
|
||||
/// <summary>
|
||||
/// 保持连接
|
||||
/// </summary>
|
||||
private bool _keepConnect;
|
||||
|
||||
/// <summary>
|
||||
@@ -208,10 +211,20 @@ namespace ModBus.Net
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回数据代理
|
||||
/// </summary>
|
||||
/// <param name="returnValue"></param>
|
||||
public delegate void ReturnValuesDelegate(KeyValuePair<int, Dictionary<string,ReturnUnit>> returnValue);
|
||||
|
||||
/// <summary>
|
||||
/// 返回数据事件
|
||||
/// </summary>
|
||||
public event ReturnValuesDelegate ReturnValues;
|
||||
|
||||
/// <summary>
|
||||
/// 获取间隔
|
||||
/// </summary>
|
||||
private int _getCycle;
|
||||
|
||||
/// <summary>
|
||||
@@ -345,13 +358,17 @@ namespace ModBus.Net
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将设备指定为未连接
|
||||
/// </summary>
|
||||
/// <param name="id">设备的id</param>
|
||||
public void MoveMachineToUnlinked(int id)
|
||||
{
|
||||
IEnumerable<BaseMachine> 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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将设备指定为已连接
|
||||
/// </summary>
|
||||
/// <param name="id">设备的id</param>
|
||||
public void MoveMachineToLinked(int id)
|
||||
{
|
||||
IEnumerable<BaseMachine> 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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已连接设备更新
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
private void MaintainTasks(object sender)
|
||||
{
|
||||
AsyncHelper.RunSync(MaintainTasksAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未连接设备更新
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
private void MaintainTasks2(object sender)
|
||||
{
|
||||
AsyncHelper.RunSync(MaintainTasks2Async);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已连接设备更新
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task MaintainTasksAsync()
|
||||
{
|
||||
HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>();
|
||||
IEnumerable<BaseMachine> saveMachinesEnum = new List<BaseMachine>();
|
||||
IEnumerable<BaseMachine> saveMachinesEnum;
|
||||
lock (_machines)
|
||||
{
|
||||
saveMachines.UnionWith(_machines);
|
||||
@@ -422,6 +455,10 @@ namespace ModBus.Net
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未连接设备更新
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task MaintainTasks2Async()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动TaskManager
|
||||
/// </summary>
|
||||
public void TaskStart()
|
||||
{
|
||||
TaskStop();
|
||||
@@ -464,6 +511,9 @@ namespace ModBus.Net
|
||||
GetCycle = TimeRestore.Restore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止TaskManager
|
||||
/// </summary>
|
||||
public void TaskStop()
|
||||
{
|
||||
lock (_machines)
|
||||
@@ -484,6 +534,11 @@ namespace ModBus.Net
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行对具体设备的数据更新
|
||||
/// </summary>
|
||||
/// <param name="machine">设备的实例</param>
|
||||
/// <returns></returns>
|
||||
private async Task RunTask(BaseMachine machine)
|
||||
{
|
||||
try
|
||||
@@ -504,10 +559,7 @@ namespace ModBus.Net
|
||||
{
|
||||
MoveMachineToLinked(machine.Id);
|
||||
}
|
||||
if (ReturnValues != null)
|
||||
{
|
||||
ReturnValues(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, ans));
|
||||
}
|
||||
ReturnValues?.Invoke(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, ans));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -515,10 +567,7 @@ namespace ModBus.Net
|
||||
{
|
||||
MoveMachineToUnlinked(machine.Id);
|
||||
}
|
||||
if (ReturnValues != null)
|
||||
{
|
||||
ReturnValues(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, null));
|
||||
}
|
||||
ReturnValues?.Invoke(new KeyValuePair<int, Dictionary<string,ReturnUnit>>(machine.Id, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ModBus.Net
|
||||
/// </summary>
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -33,10 +33,7 @@ namespace ModBus.Net
|
||||
/// <summary>
|
||||
/// 协议中的内容构造是否小端的,默认是小端构造协议。
|
||||
/// </summary>
|
||||
public static bool LittleEndian
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public static bool LittleEndian => true;
|
||||
|
||||
#region Factory
|
||||
|
||||
@@ -45,17 +42,7 @@ namespace ModBus.Net
|
||||
/// <summary>
|
||||
/// ValueHelper单例的实例
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -9,8 +9,9 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NA200H.UI.ConsoleApp</RootNamespace>
|
||||
<AssemblyName>NA200H.UI.ConsoleApp</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -9,10 +9,11 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NA200H.UI.WPF</RootNamespace>
|
||||
<AssemblyName>NA200H.UI.WPF</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本: 4.0.30319.34014
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将丢失。
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace NA200H.UI.WPF.Properties
|
||||
{
|
||||
namespace NA200H.UI.WPF.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <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.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() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的、缓存的 ResourceManager 实例。
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
@@ -52,18 +47,15 @@ namespace NA200H.UI.WPF.Properties
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为所有资源查找重写当前线程的 CurrentUICulture 属性,
|
||||
/// 方法是使用此强类型资源类。
|
||||
/// 使用此强类型资源类,为所有资源查找
|
||||
/// 重写当前线程的 CurrentUICulture 属性。
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <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>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace Siemens_S7_200.UI.WPF.TaskTest
|
||||
//增加需要通信的PLC地址
|
||||
List<AddressUnit> addressUnits = new List<AddressUnit>
|
||||
{
|
||||
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<string>();
|
||||
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");
|
||||
}
|
||||
};
|
||||
//启动任务
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Siemens_S7_200.UI.WPF.TaskTest</RootNamespace>
|
||||
<AssemblyName>Siemens_S7_200.UI.WPF.TaskTest</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
||||
@@ -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.
|
||||
|
||||
##<a name="usage"></a> Usage
|
||||
|
||||
|
||||
Reference in New Issue
Block a user