Compare commits

..

32 Commits

Author SHA1 Message Date
Kimdiego2098
d5540906cb update 3.0.0.5 2023-10-10 21:09:34 +08:00
Kimdiego2098
90796a979d fix:modbusRtu写入返回报文缓存逻辑修复 2023-10-10 21:08:42 +08:00
Kimdiego2098
2190a87772 update touchsocket 2023-10-10 20:03:40 +08:00
Kimdiego2098
c5953b83f8 update touchsocket 2023-10-10 20:02:15 +08:00
Kimdiego2098
24bc60abf0 fix:signalR razor dispose接口 2023-10-09 18:11:23 +08:00
Kimdiego2098
31eee6b009 update uaparser 2023-10-09 10:56:22 +08:00
Kimdiego2098
c5da565a8f 添加MqttRpcDemo 2023-10-07 12:04:17 +08:00
Kimdiego2098
947cd712e1 添加清理日志任务配置参数 2023-10-06 18:28:06 +08:00
Kimdiego2098
edc208f96b update 3.0.0.2 2023-10-05 15:32:50 +08:00
Diego2098
1fb0296ee7 update Directory.Build.props 2023-10-05 15:21:51 +08:00
Kimdiego2098
6488d3df87 修复重启共享通道中的单个设备时,导致通道内其他设备变量异常 2023-10-05 00:34:12 +08:00
Kimdiego2098
56189d78e0 update opcuaclient 2023-10-04 17:12:47 +08:00
Kimdiego2098
bff18127b8 update opcuaclient 2023-10-04 16:59:15 +08:00
Kimdiego2098
363206e0ba update nuget 2023-10-04 02:04:09 +08:00
Kimdiego2098
fd3e378501 update 3.0.0.1 2023-10-04 01:42:27 +08:00
Kimdiego2098
4ba2fe4c9d 实时报警列表线程同步 2023-10-04 01:27:03 +08:00
Kimdiego2098
2c499626ad modbusRtu 适配器 过滤干扰头部数据 2023-10-04 01:26:44 +08:00
Kimdiego2098
2b581a03c3 更新种子数据 2023-10-04 01:24:34 +08:00
Kimdiego2098
450c15210a update windowsService bat 2023-10-03 19:11:42 +08:00
Kimdiego2098
65fed8cc93 update demo 2023-10-03 18:54:01 +08:00
Kimdiego2098
4b64771ea2 rpc调用提示优化 2023-10-03 18:20:39 +08:00
Kimdiego2098
f39977a6ff fix:rpc 特殊方法分类错误 2023-10-03 17:05:49 +08:00
Kimdiego2098
933b535caa update demo 2023-10-02 22:37:50 +08:00
Kimdiego2098
8abc5d2f20 update driverDebugPage 2023-10-02 18:34:55 +08:00
Kimdiego2098
d8783cd994 update opcuaClient 2023-10-02 18:30:58 +08:00
Diego2098
d5d087feb5 add s7 wstring addressSign 2023-10-01 16:54:42 +08:00
Diego2098
6ba3399df7 add s7 wstring addressSign 2023-10-01 16:49:07 +08:00
Diego2098
65124b3aa8 更新demo 2023-10-01 13:33:25 +08:00
Kimdiego2098
98597f4726 update demo csproj 2023-10-01 00:33:33 +08:00
Kimdiego2098
e7981f0d8e add EncodingMapper 2023-10-01 00:25:04 +08:00
Kimdiego2098
cf654427c3 更新文档 2023-09-30 23:28:50 +08:00
Kimdiego2098
ff2f628282 默认不启用远程更新 2023-09-30 23:23:44 +08:00
540 changed files with 4540 additions and 2357 deletions

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>3.0.0.0</Version>
<Version>3.0.0.5</Version>
<LangVersion>latest</LangVersion>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Authors>Diego</Authors>

View File

@@ -13,3 +13,4 @@
global using System;
global using ThingsGateway.Components;

View File

@@ -12,6 +12,8 @@
using Microsoft.AspNetCore.Components;
using ThingsGateway.Components;
namespace ThingsGateway.Foundation.Demo;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
/// <summary>
@@ -69,7 +71,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
_periodicTimer?.Dispose();
}
/// <inheritdoc/>
public void LogOut(ThingsGateway.Foundation.LogLevel logLevel, object source, string message, Exception exception)
public void LogOut(ThingsGateway.Foundation.Core.LogLevel logLevel, object source, string message, Exception exception)
{
Messages.Add(((LogLevel)logLevel,
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {message} {exception}"));

View File

@@ -13,7 +13,7 @@
@using BlazorComponent;
@using Microsoft.AspNetCore.Components.Web;
@using Microsoft.JSInterop;
@using ThingsGateway.Foundation;
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor;
@namespace ThingsGateway.Foundation.Demo
@inherits DriverDebugUIBase

View File

@@ -15,7 +15,7 @@
@using Microsoft.AspNetCore.Components.Web;
@using System.IO.Ports;
@using System.Collections.Concurrent;
@using ThingsGateway.Foundation;
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
<div class="mb-4">通道配置</div>

View File

@@ -15,7 +15,7 @@
@using Microsoft.AspNetCore.Components.Web;
@using System.IO.Ports;
@using System.Collections.Concurrent;
@using ThingsGateway.Foundation;
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">

View File

@@ -15,7 +15,7 @@
@using Microsoft.AspNetCore.Components.Web;
@using System.IO.Ports;
@using System.Collections.Concurrent;
@using ThingsGateway.Foundation;
@using ThingsGateway.Foundation.Core;
@using Masa.Blazor
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">

View File

@@ -15,5 +15,7 @@ global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Components;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -124,6 +124,15 @@ public partial class MainLayout
"Title": "OPCUAClient"
}
]
},
{
"Title": "Mqtt",
"Children": [
{
"Href": "/MqttClient",
"Title": "MqttClient"
}
]
}
]

View File

@@ -31,11 +31,11 @@
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Vigor\ThingsGateway.Foundation.Adapter.Vigor.csproj" />
<Compile Include="..\..\PluginProGasCustom\ThingsGateway.Plugin.GasCustom\Page\GasCustomSerialDebugPage.razor.cs" Link="Pages\GasCustom\GasCustomSerialDebugPage.razor.cs" />
<Compile Include="..\..\PluginProGasCustom\ThingsGateway.Plugin.GasCustom\Page\GasCustomSerialOverTcpDebugPage.razor.cs" Link="Pages\GasCustom\GasCustomSerialOverTcpDebugPage.razor.cs" />
<Content Include="..\..\PluginProGasCustom\ThingsGateway.Plugin.GasCustom\Page\GasCustomSerialDebugPage.razor" Link="Pages\GasCustom\GasCustomSerialDebugPage.razor" />
<Content Include="..\..\PluginProGasCustom\ThingsGateway.Plugin.GasCustom\Page\GasCustomSerialOverTcpDebugPage.razor" Link="GasCustom\Vigor\GasCustomSerialOverTcpDebugPage.razor" />
<ProjectReference Include="..\..\PluginProGasCustom\ThingsGateway.Foundation.Adapter.GasCustom\ThingsGateway.Foundation.Adapter.GasCustom.csproj" />
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialDebugPage.razor.cs" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialDebugPage.razor.cs" />
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialOverTcpDebugPage.razor.cs" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialOverTcpDebugPage.razor.cs" />
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialDebugPage.razor" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialDebugPage.razor" />
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialOverTcpDebugPage.razor" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialOverTcpDebugPage.razor" />
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.HZW_QTJC_01\ThingsGateway.Foundation.Adapter.HZW_QTJC_01.csproj" />
@@ -45,6 +45,13 @@
<ItemGroup>
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007DebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\MqttRpcNameVaueWithId.cs" Link="Pages\Mqtt\MqttRpcNameVaueWithId.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor.cs" Link="Pages\Mqtt\MqttClientDebugPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor.cs" Link="Pages\Mqtt\MqttClientPage.razor.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\PrivateLogger.cs" Link="Pages\Mqtt\PrivateLogger.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClient.cs" Link="Pages\Mqtt\MqttRpcClient.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor" Link="Pages\DLT645\DLT645_2007DebugPage.razor" />
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor.cs" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor" />
@@ -117,5 +124,17 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Pages\Mqtt\" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor" Link="Pages\Mqtt\MqttClientDebugPage.razor" />
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor" Link="Pages\Mqtt\MqttClientPage.razor" />
<PackageReference Include="MQTTnet" Version="4.3.1.873" />
</ItemGroup>
</Project>

View File

@@ -19,7 +19,7 @@
@using BlazorComponent
@using Masa.Blazor
@using Masa.Blazor.Presets
@using ThingsGateway.Foundation;
@using ThingsGateway.Foundation.Core;
@using ThingsGateway.Components;
@using ThingsGateway.Core;
@using System.Net.Http.Json

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>3.0.0.0</Version>
<Version>3.0.0.5</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.Text;
using ThingsGateway.Foundation.Extension.Generic;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
using ThingsGateway.Foundation.Extension.Generic;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
using ThingsGateway.Foundation.Extension.Generic;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
namespace ThingsGateway.Foundation.Adapter.DLT645;

View File

@@ -11,9 +11,11 @@
#endregion
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -261,7 +261,7 @@
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.#ctor(ThingsGateway.Foundation.EndianType)">
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.#ctor(ThingsGateway.Foundation.Core.EndianType)">
<summary>
DLT645_2007
</summary>
@@ -304,7 +304,7 @@
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.#ctor(ThingsGateway.Foundation.TcpClient)">
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.#ctor(ThingsGateway.Foundation.Core.TcpClient)">
<summary>
DLT645_2007
</summary>

View File

@@ -11,9 +11,11 @@
#endregion
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Serial;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -91,9 +91,17 @@ internal class ModbusHelper
if (response[1] >= 0x80)//错误码
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
if ((response.Length < response[2] + 3))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
if (response[1] <= 0x05)
{
if ((response.Length < response[2] + 3))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
}
else
{
if ((response.Length < 6))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
}
if (send.Length == 0)
{
@@ -126,15 +134,20 @@ internal class ModbusHelper
if (response[1] >= 0x80)//错误码
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
if ((response.Length < response[2] + 5))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
if (response[1] <= 0x05)
{
if ((response.Length < response[2] + 5))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
if (response[2] == 0)
}
else
{
if ((response.Length < 8))
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
}
var data = response.SelectMiddle(0, response[2] != 0 ? response[2] + 5 : 8);
if (crcCheck && !EasyCRC16.CheckCRC16(data))
return new OperResult<byte[], FilterResult>("Crc校验失败" + DataTransUtil.ByteToHexString(data, ' ')) { Content2 = FilterResult.Success };

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;

View File

@@ -10,6 +10,8 @@
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Modbus;
/// <summary>
@@ -41,20 +43,43 @@ public class ModbusRtuDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<M
/// <inheritdoc/>
protected override FilterResult UnpackResponse(ModbusRtuMessage request, byte[] send, byte[] body, byte[] response)
{
//理想状态检测
var result = ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
if (result.IsSuccess)
//链路干扰时需剔除前缀中的多于字节,初步按站号+功能码找寻初始字节
if (send?.Length > 0)
{
request.ErrorCode = result.ErrorCode;
request.Message = result.Message;
request.Content = result.Content;
int index = -1;
for (int i = 0; i < response.Length - 1; i++)
{
if (response[i] == send[0] && (response[i + 1] == send[1] || response[i + 1] == (send[1] + 0x80)))
{
index = i;
break;
}
}
if (index >= 0)
{
response = response.RemoveBegin(index);
}
//理想状态检测
var result = ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
if (result.IsSuccess)
{
request.ErrorCode = result.ErrorCode;
request.Message = result.Message;
request.Content = result.Content;
}
else
{
request.ErrorCode = result.ErrorCode;
request.Message = result.Message;
}
return result.Content2;
}
else
{
request.ErrorCode = result.ErrorCode;
request.Message = result.Message;
return FilterResult.Success;
}
return result.Content2;
}
}

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;

View File

@@ -11,7 +11,6 @@
#endregion
using System.Collections.Concurrent;
using System.Collections.Generic;
using ThingsGateway.Foundation.Extension.Bool;
using ThingsGateway.Foundation.Extension.Generic;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;

View File

@@ -11,7 +11,6 @@
#endregion
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using ThingsGateway.Foundation.Extension.Bool;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.ComponentModel;
namespace ThingsGateway.Foundation.Adapter.Modbus;

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using ThingsGateway.Foundation.Extension.Generic;
using ThingsGateway.Foundation.Extension.String;

View File

@@ -406,7 +406,7 @@
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Received(ThingsGateway.Foundation.Sockets.SocketClient,ThingsGateway.Foundation.IRequestInfo)">
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Received(ThingsGateway.Foundation.Sockets.SocketClient,ThingsGateway.Foundation.Core.IRequestInfo)">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter">
@@ -598,7 +598,7 @@
PackHelper
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.PackHelper.ModbusLoadSourceRead``2(ThingsGateway.Foundation.IReadWrite,System.Collections.Generic.List{``1},System.Int32)">
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.PackHelper.ModbusLoadSourceRead``2(ThingsGateway.Foundation.Core.IReadWrite,System.Collections.Generic.List{``1},System.Int32)">
<summary>
打包变量,添加到<see href="deviceVariableSourceReads"></see>
</summary>

View File

@@ -441,7 +441,7 @@
当前保存的需订阅列表
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.#ctor(ThingsGateway.Foundation.ILog)">
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.#ctor(ThingsGateway.Foundation.Core.ILog)">
<summary>
<inheritdoc/>
</summary>

View File

@@ -682,14 +682,632 @@ public class OPCUAClient : IDisposable
}
NodeId nodeToRead = new(nodeIdStr);
var node = (VariableNode)await m_session.ReadNodeAsync(nodeToRead, cancellationToken);
await typeSystem.LoadType(node.DataType, true, true);
var node = (VariableNode)await ReadNodeAsync(nodeToRead, NodeClass.Unspecified, false, cancellationToken);
await typeSystem.LoadType(node.DataType, true, false);
_variableDicts.AddOrUpdate(nodeIdStr, node);
return node;
}
#endregion
#region session
/// <inheritdoc/>
public async Task<Node> ReadNodeAsync(
NodeId nodeId,
NodeClass nodeClass,
bool optionalAttributes = true,
CancellationToken ct = default)
{
// build list of attributes.
var attributes = CreateAttributes(nodeClass, optionalAttributes);
// build list of values to read.
ReadValueIdCollection itemsToRead = new ReadValueIdCollection();
foreach (uint attributeId in attributes.Keys)
{
ReadValueId itemToRead = new ReadValueId
{
NodeId = nodeId,
AttributeId = attributeId
};
itemsToRead.Add(itemToRead);
}
// read from server.
ReadResponse readResponse = await m_session.ReadAsync(
null,
0,
TimestampsToReturn.Neither,
itemsToRead, ct).ConfigureAwait(false);
DataValueCollection values = readResponse.Results;
DiagnosticInfoCollection diagnosticInfos = readResponse.DiagnosticInfos;
ClientBase.ValidateResponse(values, itemsToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, itemsToRead);
return ProcessReadResponse(readResponse.ResponseHeader, attributes, itemsToRead, values, diagnosticInfos);
}
/// <summary>
/// Creates a Node based on the read response.
/// </summary>
private Node ProcessReadResponse(
ResponseHeader responseHeader,
IDictionary<uint, DataValue> attributes,
ReadValueIdCollection itemsToRead,
DataValueCollection values,
DiagnosticInfoCollection diagnosticInfos)
{
// process results.
int? nodeClass = null;
for (int ii = 0; ii < itemsToRead.Count; ii++)
{
uint attributeId = itemsToRead[ii].AttributeId;
// the node probably does not exist if the node class is not found.
if (attributeId == Attributes.NodeClass)
{
if (!DataValue.IsGood(values[ii]))
{
throw ServiceResultException.Create(values[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable);
}
// check for valid node class.
nodeClass = values[ii].Value as int?;
if (nodeClass == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Node does not have a valid value for NodeClass: {0}.", values[ii].Value);
}
}
else
{
if (!DataValue.IsGood(values[ii]))
{
// check for unsupported attributes.
if (values[ii].StatusCode == StatusCodes.BadAttributeIdInvalid)
{
continue;
}
// ignore errors on optional attributes
if (StatusCode.IsBad(values[ii].StatusCode))
{
if (attributeId == Attributes.AccessRestrictions ||
attributeId == Attributes.Description ||
attributeId == Attributes.RolePermissions ||
attributeId == Attributes.UserRolePermissions ||
attributeId == Attributes.DataTypeDefinition ||
attributeId == Attributes.AccessLevelEx ||
attributeId == Attributes.UserWriteMask ||
attributeId == Attributes.WriteMask)
{
continue;
}
}
// all supported attributes must be readable.
if (attributeId != Attributes.Value)
{
throw ServiceResultException.Create(values[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable);
}
}
}
attributes[attributeId] = values[ii];
}
Node node;
DataValue value;
switch ((NodeClass)nodeClass.Value)
{
default:
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Node does not have a valid value for NodeClass: {0}.", nodeClass.Value);
}
case NodeClass.Object:
{
ObjectNode objectNode = new ObjectNode();
value = attributes[Attributes.EventNotifier];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Object does not support the EventNotifier attribute.");
}
objectNode.EventNotifier = (byte)value.GetValue(typeof(byte));
node = objectNode;
break;
}
case NodeClass.ObjectType:
{
ObjectTypeNode objectTypeNode = new ObjectTypeNode();
value = attributes[Attributes.IsAbstract];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "ObjectType does not support the IsAbstract attribute.");
}
objectTypeNode.IsAbstract = (bool)value.GetValue(typeof(bool));
node = objectTypeNode;
break;
}
case NodeClass.Variable:
{
VariableNode variableNode = new VariableNode();
// DataType Attribute
value = attributes[Attributes.DataType];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Variable does not support the DataType attribute.");
}
variableNode.DataType = (NodeId)value.GetValue(typeof(NodeId));
// ValueRank Attribute
value = attributes[Attributes.ValueRank];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Variable does not support the ValueRank attribute.");
}
variableNode.ValueRank = (int)value.GetValue(typeof(int));
// ArrayDimensions Attribute
value = attributes[Attributes.ArrayDimensions];
if (value != null)
{
if (value.Value == null)
{
variableNode.ArrayDimensions = Array.Empty<uint>();
}
else
{
variableNode.ArrayDimensions = (uint[])value.GetValue(typeof(uint[]));
}
}
// AccessLevel Attribute
value = attributes[Attributes.AccessLevel];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Variable does not support the AccessLevel attribute.");
}
variableNode.AccessLevel = (byte)value.GetValue(typeof(byte));
// UserAccessLevel Attribute
value = attributes[Attributes.UserAccessLevel];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Variable does not support the UserAccessLevel attribute.");
}
variableNode.UserAccessLevel = (byte)value.GetValue(typeof(byte));
// Historizing Attribute
value = attributes[Attributes.Historizing];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Variable does not support the Historizing attribute.");
}
variableNode.Historizing = (bool)value.GetValue(typeof(bool));
// MinimumSamplingInterval Attribute
value = attributes[Attributes.MinimumSamplingInterval];
if (value != null)
{
variableNode.MinimumSamplingInterval = Convert.ToDouble(attributes[Attributes.MinimumSamplingInterval].Value);
}
// AccessLevelEx Attribute
value = attributes[Attributes.AccessLevelEx];
if (value != null)
{
variableNode.AccessLevelEx = (uint)value.GetValue(typeof(uint));
}
node = variableNode;
break;
}
case NodeClass.VariableType:
{
VariableTypeNode variableTypeNode = new VariableTypeNode();
// IsAbstract Attribute
value = attributes[Attributes.IsAbstract];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "VariableType does not support the IsAbstract attribute.");
}
variableTypeNode.IsAbstract = (bool)value.GetValue(typeof(bool));
// DataType Attribute
value = attributes[Attributes.DataType];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "VariableType does not support the DataType attribute.");
}
variableTypeNode.DataType = (NodeId)value.GetValue(typeof(NodeId));
// ValueRank Attribute
value = attributes[Attributes.ValueRank];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "VariableType does not support the ValueRank attribute.");
}
variableTypeNode.ValueRank = (int)value.GetValue(typeof(int));
// ArrayDimensions Attribute
value = attributes[Attributes.ArrayDimensions];
if (value != null && value.Value != null)
{
variableTypeNode.ArrayDimensions = (uint[])value.GetValue(typeof(uint[]));
}
node = variableTypeNode;
break;
}
case NodeClass.Method:
{
MethodNode methodNode = new MethodNode();
// Executable Attribute
value = attributes[Attributes.Executable];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Method does not support the Executable attribute.");
}
methodNode.Executable = (bool)value.GetValue(typeof(bool));
// UserExecutable Attribute
value = attributes[Attributes.UserExecutable];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Method does not support the UserExecutable attribute.");
}
methodNode.UserExecutable = (bool)value.GetValue(typeof(bool));
node = methodNode;
break;
}
case NodeClass.DataType:
{
DataTypeNode dataTypeNode = new DataTypeNode();
// IsAbstract Attribute
value = attributes[Attributes.IsAbstract];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "DataType does not support the IsAbstract attribute.");
}
dataTypeNode.IsAbstract = (bool)value.GetValue(typeof(bool));
// DataTypeDefinition Attribute
value = attributes[Attributes.DataTypeDefinition];
if (value != null)
{
dataTypeNode.DataTypeDefinition = value.Value as ExtensionObject;
}
node = dataTypeNode;
break;
}
case NodeClass.ReferenceType:
{
ReferenceTypeNode referenceTypeNode = new ReferenceTypeNode();
// IsAbstract Attribute
value = attributes[Attributes.IsAbstract];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "ReferenceType does not support the IsAbstract attribute.");
}
referenceTypeNode.IsAbstract = (bool)value.GetValue(typeof(bool));
// Symmetric Attribute
value = attributes[Attributes.Symmetric];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "ReferenceType does not support the Symmetric attribute.");
}
referenceTypeNode.Symmetric = (bool)value.GetValue(typeof(bool));
// InverseName Attribute
value = attributes[Attributes.InverseName];
if (value != null && value.Value != null)
{
referenceTypeNode.InverseName = (LocalizedText)value.GetValue(typeof(LocalizedText));
}
node = referenceTypeNode;
break;
}
case NodeClass.View:
{
ViewNode viewNode = new ViewNode();
// EventNotifier Attribute
value = attributes[Attributes.EventNotifier];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "View does not support the EventNotifier attribute.");
}
viewNode.EventNotifier = (byte)value.GetValue(typeof(byte));
// ContainsNoLoops Attribute
value = attributes[Attributes.ContainsNoLoops];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "View does not support the ContainsNoLoops attribute.");
}
viewNode.ContainsNoLoops = (bool)value.GetValue(typeof(bool));
node = viewNode;
break;
}
}
// NodeId Attribute
value = attributes[Attributes.NodeId];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Node does not support the NodeId attribute.");
}
node.NodeId = (NodeId)value.GetValue(typeof(NodeId));
node.NodeClass = (NodeClass)nodeClass.Value;
// BrowseName Attribute
value = attributes[Attributes.BrowseName];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Node does not support the BrowseName attribute.");
}
node.BrowseName = (QualifiedName)value.GetValue(typeof(QualifiedName));
// DisplayName Attribute
value = attributes[Attributes.DisplayName];
if (value == null)
{
throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Node does not support the DisplayName attribute.");
}
node.DisplayName = (LocalizedText)value.GetValue(typeof(LocalizedText));
// all optional attributes follow
// Description Attribute
if (attributes.TryGetValue(Attributes.Description, out value) &&
value != null && value.Value != null)
{
node.Description = (LocalizedText)value.GetValue(typeof(LocalizedText));
}
// WriteMask Attribute
if (attributes.TryGetValue(Attributes.WriteMask, out value) &&
value != null)
{
node.WriteMask = (uint)value.GetValue(typeof(uint));
}
// UserWriteMask Attribute
if (attributes.TryGetValue(Attributes.UserWriteMask, out value) &&
value != null)
{
node.UserWriteMask = (uint)value.GetValue(typeof(uint));
}
// RolePermissions Attribute
if (attributes.TryGetValue(Attributes.RolePermissions, out value) &&
value != null)
{
ExtensionObject[] rolePermissions = value.Value as ExtensionObject[];
if (rolePermissions != null)
{
node.RolePermissions = new RolePermissionTypeCollection();
foreach (ExtensionObject rolePermission in rolePermissions)
{
node.RolePermissions.Add(rolePermission.Body as RolePermissionType);
}
}
}
// UserRolePermissions Attribute
if (attributes.TryGetValue(Attributes.UserRolePermissions, out value) &&
value != null)
{
ExtensionObject[] userRolePermissions = value.Value as ExtensionObject[];
if (userRolePermissions != null)
{
node.UserRolePermissions = new RolePermissionTypeCollection();
foreach (ExtensionObject rolePermission in userRolePermissions)
{
node.UserRolePermissions.Add(rolePermission.Body as RolePermissionType);
}
}
}
// AccessRestrictions Attribute
if (attributes.TryGetValue(Attributes.AccessRestrictions, out value) &&
value != null)
{
node.AccessRestrictions = (ushort)value.GetValue(typeof(ushort));
}
return node;
}
/// <summary>
/// Create a dictionary of attributes to read for a nodeclass.
/// </summary>
private IDictionary<uint, DataValue> CreateAttributes(NodeClass nodeclass = NodeClass.Unspecified, bool optionalAttributes = true)
{
// Attributes to read for all types of nodes
var attributes = new SortedDictionary<uint, DataValue>() {
{ Attributes.NodeId, null },
{ Attributes.NodeClass, null },
{ Attributes.BrowseName, null },
{ Attributes.DisplayName, null },
};
switch (nodeclass)
{
case NodeClass.Object:
attributes.Add(Attributes.EventNotifier, null);
break;
case NodeClass.Variable:
attributes.Add(Attributes.DataType, null);
attributes.Add(Attributes.ValueRank, null);
attributes.Add(Attributes.ArrayDimensions, null);
attributes.Add(Attributes.AccessLevel, null);
attributes.Add(Attributes.UserAccessLevel, null);
attributes.Add(Attributes.Historizing, null);
attributes.Add(Attributes.MinimumSamplingInterval, null);
attributes.Add(Attributes.AccessLevelEx, null);
break;
case NodeClass.Method:
attributes.Add(Attributes.Executable, null);
attributes.Add(Attributes.UserExecutable, null);
break;
case NodeClass.ObjectType:
attributes.Add(Attributes.IsAbstract, null);
break;
case NodeClass.VariableType:
attributes.Add(Attributes.IsAbstract, null);
attributes.Add(Attributes.DataType, null);
attributes.Add(Attributes.ValueRank, null);
attributes.Add(Attributes.ArrayDimensions, null);
break;
case NodeClass.ReferenceType:
attributes.Add(Attributes.IsAbstract, null);
attributes.Add(Attributes.Symmetric, null);
attributes.Add(Attributes.InverseName, null);
break;
case NodeClass.DataType:
attributes.Add(Attributes.IsAbstract, null);
attributes.Add(Attributes.DataTypeDefinition, null);
break;
case NodeClass.View:
attributes.Add(Attributes.EventNotifier, null);
attributes.Add(Attributes.ContainsNoLoops, null);
break;
default:
// build complete list of attributes.
attributes = new SortedDictionary<uint, DataValue> {
{ Attributes.NodeId, null },
{ Attributes.NodeClass, null },
{ Attributes.BrowseName, null },
{ Attributes.DisplayName, null },
//{ Attributes.Description, null },
//{ Attributes.WriteMask, null },
//{ Attributes.UserWriteMask, null },
{ Attributes.DataType, null },
{ Attributes.ValueRank, null },
{ Attributes.ArrayDimensions, null },
{ Attributes.AccessLevel, null },
{ Attributes.UserAccessLevel, null },
{ Attributes.MinimumSamplingInterval, null },
{ Attributes.Historizing, null },
{ Attributes.EventNotifier, null },
{ Attributes.Executable, null },
{ Attributes.UserExecutable, null },
{ Attributes.IsAbstract, null },
{ Attributes.InverseName, null },
{ Attributes.Symmetric, null },
{ Attributes.ContainsNoLoops, null },
{ Attributes.DataTypeDefinition, null },
//{ Attributes.RolePermissions, null },
//{ Attributes.UserRolePermissions, null },
//{ Attributes.AccessRestrictions, null },
{ Attributes.AccessLevelEx, null }
};
break;
}
if (optionalAttributes)
{
attributes.Add(Attributes.Description, null);
attributes.Add(Attributes.WriteMask, null);
attributes.Add(Attributes.UserWriteMask, null);
attributes.Add(Attributes.RolePermissions, null);
attributes.Add(Attributes.UserRolePermissions, null);
attributes.Add(Attributes.AccessRestrictions, null);
}
return attributes;
}
#endregion
#region
/// <summary>

View File

@@ -304,7 +304,7 @@
SessionReconnectHandler
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.#ctor(ThingsGateway.Foundation.ILog)">
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.#ctor(ThingsGateway.Foundation.Core.ILog)">
<summary>
默认的构造函数实例化一个新的OPC UA类
</summary>

View File

@@ -11,8 +11,10 @@
#endregion
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Sockets;

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
using ThingsGateway.Foundation.Extension.String;
using ThingsGateway.Foundation.Extension;
namespace ThingsGateway.Foundation.Adapter.Siemens;
/// <summary>
@@ -54,7 +54,10 @@ public class SiemensAddress : DeviceAddressBase
/// DB块数据信息
/// </summary>
public ushort DbBlock { get; set; }
/// <summary>
/// IsWString默认是true如果不是WString,需要填写W=false;
/// </summary>
public bool IsWString { get; set; } = true;
/// <summary>
/// 获取起始地址
/// </summary>
@@ -103,127 +106,132 @@ public class SiemensAddress : DeviceAddressBase
public static SiemensAddress ParseFrom(string address)
{
SiemensAddress s7AddressData = new();
address = address.ToUpper();
address = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
string[] strArr = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
for (int index = 0; index < strArr.Length; ++index)
{
if (strArr[index].StartsWith("W="))
{
s7AddressData.IsWString = strArr[index].Substring(2).ToBoolean(true);
}
else if (!strArr[index].Contains("="))
{
s7AddressData.DbBlock = 0;
if (address.StartsWith("AI"))
{
s7AddressData.DataCode = (byte)S7Area.AI;
if (address.StartsWith("AIX") || address.StartsWith("AIB") || address.StartsWith("AIW") || address.StartsWith("AID"))
{
s7AddressData.Address = GetAddressStart(address.Substring(3)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(3));
}
else
{
s7AddressData.Address = GetAddressStart(address.Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(2));
}
}
else if (address.StartsWith("AQ"))
{
s7AddressData.DataCode = (byte)S7Area.AQ;
if (address.StartsWith("AQX") || address.StartsWith("AQB") || address.StartsWith("AQW") || address.StartsWith("AQD"))
{
s7AddressData.Address = GetAddressStart(address.Substring(3)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(3));
}
else
{
s7AddressData.Address = GetAddressStart(address.Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(2));
}
}
else if (address[0] == 'I')
{
s7AddressData.DataCode = (byte)S7Area.PE;
if (address.StartsWith("IX") || address.StartsWith("IB") || address.StartsWith("IW") || address.StartsWith("ID"))
{
s7AddressData.Address = GetAddressStart(address.Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(address.Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(1));
}
}
else if (address[0] == 'Q')
{
s7AddressData.DataCode = (byte)S7Area.PA;
if (address.StartsWith("QX") || address.StartsWith("QB") || address.StartsWith("QW") || address.StartsWith("QD"))
{
s7AddressData.Address = GetAddressStart(address.Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(address.Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(1));
}
}
else if (address[0] == 'M')
{
s7AddressData.DataCode = (byte)S7Area.MK;
if (address.StartsWith("MX") || address.StartsWith("MB") || address.StartsWith("MW") || address.StartsWith("MD"))
{
s7AddressData.Address = GetAddressStart(address.Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(address.Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(1));
}
}
else if (address[0] == 'D' || address.Substring(0, 2) == "DB")
{
s7AddressData.DataCode = (byte)S7Area.DB;
string[] strArray = address.Split('.');
s7AddressData.DbBlock = address[1] != 'B' ? Convert.ToUInt16(strArray[0].Substring(1)) : Convert.ToUInt16(strArray[0].Substring(2));
string address1 = address.Substring(address.IndexOf('.') + 1);
if (address1.StartsWith("DBX") || address1.StartsWith("DBB") || address1.StartsWith("DBW") || address1.StartsWith("DBD"))
{
address1 = address1.Substring(3);
}
s7AddressData.DbBlock = 0;
s7AddressData.Address = GetAddressStart(address1).ToString();
s7AddressData.BitCode = GetBitCode(address1);
}
else if (address[0] == 'T')
{
s7AddressData.DataCode = (byte)S7Area.TM;
s7AddressData.Address = GetAddressStart(address.Substring(1), true).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(1));
}
else if (address[0] == 'C')
{
s7AddressData.DataCode = (byte)S7Area.CT;
s7AddressData.Address = GetAddressStart(address.Substring(1), true).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(1));
}
else if (address[0] == 'V')
{
s7AddressData.DataCode = (byte)S7Area.DB;
s7AddressData.DbBlock = 1;
if (address.StartsWith("VB") || address.StartsWith("VW") || address.StartsWith("VD") || address.StartsWith("VX"))
{
s7AddressData.Address = GetAddressStart(address.Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(address.Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(address.Substring(1));
}
}
else
{
throw new Exception("解析错误,无相关变量类型");
}
if (strArr[index].StartsWith("AI"))
{
s7AddressData.DataCode = (byte)S7Area.AI;
if (strArr[index].StartsWith("AIX") || strArr[index].StartsWith("AIB") || strArr[index].StartsWith("AIW") || strArr[index].StartsWith("AID"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(3)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(3));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
}
else if (strArr[index].StartsWith("AQ"))
{
s7AddressData.DataCode = (byte)S7Area.AQ;
if (strArr[index].StartsWith("AQX") || strArr[index].StartsWith("AQB") || strArr[index].StartsWith("AQW") || strArr[index].StartsWith("AQD"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(3)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(3));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
}
else if (strArr[index][0] == 'I')
{
s7AddressData.DataCode = (byte)S7Area.PE;
if (strArr[index].StartsWith("IX") || strArr[index].StartsWith("IB") || strArr[index].StartsWith("IW") || strArr[index].StartsWith("ID"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
else if (strArr[index][0] == 'Q')
{
s7AddressData.DataCode = (byte)S7Area.PA;
if (strArr[index].StartsWith("QX") || strArr[index].StartsWith("QB") || strArr[index].StartsWith("QW") || strArr[index].StartsWith("QD"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
else if (strArr[index][0] == 'M')
{
s7AddressData.DataCode = (byte)S7Area.MK;
if (strArr[index].StartsWith("MX") || strArr[index].StartsWith("MB") || strArr[index].StartsWith("MW") || strArr[index].StartsWith("MD"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
else if (strArr[index][0] == 'D' || strArr[index].Substring(0, 2) == "DB")
{
s7AddressData.DataCode = (byte)S7Area.DB;
string[] strArray = strArr[index].Split('.');
s7AddressData.DbBlock = strArray[index][1] != 'B' ? Convert.ToUInt16(strArray[0].Substring(1)) : Convert.ToUInt16(strArray[0].Substring(2));
string address1 = strArr[index].Substring(strArr[index].IndexOf('.') + 1);
if (address1.StartsWith("DBX") || address1.StartsWith("DBB") || address1.StartsWith("DBW") || address1.StartsWith("DBD"))
{
address1 = address1.Substring(3);
}
s7AddressData.Address = GetAddressStart(address1).ToString();
s7AddressData.BitCode = GetBitCode(address1);
}
else if (strArr[index][0] == 'T')
{
s7AddressData.DataCode = (byte)S7Area.TM;
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1), true).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
else if (strArr[index][0] == 'C')
{
s7AddressData.DataCode = (byte)S7Area.CT;
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1), true).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
else if (strArr[index][0] == 'V')
{
s7AddressData.DataCode = (byte)S7Area.DB;
s7AddressData.DbBlock = 1;
if (strArr[index].StartsWith("VB") || strArr[index].StartsWith("VW") || strArr[index].StartsWith("VD") || strArr[index].StartsWith("VX"))
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(2)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(2));
}
else
{
s7AddressData.Address = GetAddressStart(strArr[index].Substring(1)).ToString();
s7AddressData.BitCode = GetBitCode(strArr[index].Substring(1));
}
}
}
}
return s7AddressData;
}
@@ -242,39 +250,39 @@ public class SiemensAddress : DeviceAddressBase
{
if (DataCode == (byte)S7Area.TM)
{
return "T" + Address.ToString();
return "T" + Address.ToString() + (IsWString ? ";W=true;" : ";W=false;");
}
if (DataCode == (byte)S7Area.CT)
{
return "C" + Address.ToString();
return "C" + Address.ToString() + (IsWString ? ";W=true;" : ";W=false;");
}
if (DataCode == (byte)S7Area.AI)
{
return "AI" + GetStringAddress(AddressStart);
return "AI" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
}
if (DataCode == (byte)S7Area.AQ)
{
return "AQ" + GetStringAddress(AddressStart);
return "AQ" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
}
if (DataCode == (byte)S7Area.PE)
{
return "I" + GetStringAddress(AddressStart);
return "I" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
}
if (DataCode == (byte)S7Area.PA)
{
return "Q" + GetStringAddress(AddressStart);
return "Q" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
}
if (DataCode == (byte)S7Area.MK)
{
return "M" + GetStringAddress(AddressStart);
return "M" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
}
return DataCode == (byte)S7Area.DB ? "DB" + DbBlock.ToString() + "." + GetStringAddress(AddressStart) : Address.ToString();
return DataCode == (byte)S7Area.DB ? "DB" + DbBlock.ToString() + "." + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;") : Address.ToString() + (IsWString ? ";W=true;" : ";W=false;");
}
private static string GetStringAddress(int addressStart)

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
namespace ThingsGateway.Foundation.Adapter.Siemens;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
namespace ThingsGateway.Foundation.Adapter.Siemens;
@@ -28,8 +27,7 @@ internal static class PackHelper
IThingsGatewayBitConverter transformParameter = ByteTransformUtil.GetTransByAddress(ref address, byteConverter);
item.ThingsGatewayBitConverter = transformParameter;
item.VariableAddress = address;//需要使用过滤后的地址
//item.VariableAddress = address;//需要使用过滤后的地址
item.Index = siemensS7Net.GetBitOffset(item.VariableAddress);
}
//按读取间隔分组
@@ -38,43 +36,55 @@ internal static class PackHelper
{
Dictionary<SiemensAddress, T2> map = item.ToDictionary(it =>
{
var lastLen = it.DataTypeEnum.GetByteLength();
if (lastLen <= 0)
{
switch (it.DataTypeEnum)
{
case DataTypeEnum.String:
if (it.ThingsGatewayBitConverter.Length == null)
{
throw new("数据类型为字符串时,必须指定字符串长度,才能进行打包");
}
else
{
if (siemensS7Net.CurrentPlc == SiemensEnum.S200Smart)
{
//字符串在S200Smart中第一个字节不属于实际内容
it.Index += 1;
//it.ThingsGatewayBitConverter.StringLength -= 1;
lastLen = it.ThingsGatewayBitConverter.Length.Value + 1;
}
else
{
//字符串在S7中前两个字节不属于实际内容
it.Index += 2;
//it.ThingsGatewayBitConverter.StringLength -= 2;
lastLen = it.ThingsGatewayBitConverter.Length.Value + 2;
}
}
break;
default:
lastLen = 1;
break;
}
}
try
{
var s7Address = SiemensAddress.ParseFrom(it.VariableAddress);
var lastLen = it.DataTypeEnum.GetByteLength();
if (lastLen <= 0)
{
switch (it.DataTypeEnum)
{
case DataTypeEnum.String:
if (it.ThingsGatewayBitConverter.Length == null)
{
throw new("数据类型为字符串时,必须指定字符串长度,才能进行打包");
}
else
{
if (siemensS7Net.CurrentPlc == SiemensEnum.S200Smart)
{
if (s7Address.IsWString)
{
//字符串在S200Smart中第一个字节不属于实际内容
it.Index += 1;
lastLen = it.ThingsGatewayBitConverter.Length.Value + 1;
}
else
{
lastLen = it.ThingsGatewayBitConverter.Length.Value;
}
}
else
{
if (s7Address.IsWString)
{
//字符串在S7中前两个字节不属于实际内容
it.Index += 2;
lastLen = it.ThingsGatewayBitConverter.Length.Value + 2;
}
else
{
lastLen = it.ThingsGatewayBitConverter.Length.Value;
}
}
}
break;
default:
lastLen = 1;
break;
}
}
if ((s7Address.DataCode == (byte)S7WordLength.Counter || s7Address.DataCode == (byte)S7WordLength.Timer) && lastLen == 1)
{
lastLen = 2;

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.Text;
using ThingsGateway.Foundation.Extension.Generic;

View File

@@ -10,8 +10,6 @@
//------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation.Adapter.Siemens;

View File

@@ -222,7 +222,7 @@
相关命令含义源自网络资料/Shrap7/s7netplus
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.#ctor(ThingsGateway.Foundation.TcpClient,ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum)">
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.#ctor(ThingsGateway.Foundation.Core.TcpClient,ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum)">
<summary>
传入PLC类型程序内会改变相应PLC类型的S7协议LocalTSAP RemoteTSAP等
</summary>

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 设备地址数据的信息,对每个协议都建立其变量地址的表示类

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 打包读取变量

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 打包读取变量
/// </summary>

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 设备读写接口

View File

@@ -15,7 +15,7 @@ using System.Text;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 读写扩展方法

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// TCP读写设备

View File

@@ -12,7 +12,7 @@
using System.ComponentModel;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// TCP读写设备

View File

@@ -12,7 +12,7 @@
using System.ComponentModel;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 服务设备

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// UDP读写设备

View File

@@ -12,7 +12,7 @@
using System.Collections;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 线程安全的LinkedList

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// HSL摘录用于CRC16验证的类

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 自增

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// EasyLock使用轻量级SemaphoreSlim锁只允许一个并发量并记录并发信息

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// TimerTick

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 常量

View File

@@ -12,7 +12,7 @@
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// TCP/Serial适配器基类

View File

@@ -14,7 +14,7 @@ using System.Net;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// UDP适配器基类

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 数据类型

View File

@@ -12,7 +12,7 @@
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <inheritdoc/>
public static class ByteExtensions

View File

@@ -12,7 +12,7 @@
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 对象拓展

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>

View File

@@ -178,6 +178,10 @@ public static class GenericExtensions
/// <inheritdoc cref="DataTransUtil.SpliceArray" />
public static T[] SpliceArray<T>(this T[] value, params T[][] arrays)
{
if (value == null)
{
value = new T[0];
}
List<T[]> objArrayList = new(arrays.Length + 1)
{
value

View File

@@ -12,7 +12,7 @@
using System.Reflection;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// Method Info 拓展

View File

@@ -322,6 +322,7 @@ public static class StringExtensions
/// <returns></returns>
public static bool ToBoolean(this string value, bool defaultValue = false) => value?.ToUpper() switch
{
"0" or "FALSE" => false,
"1" or "TRUE" => true,
_ => defaultValue,
};

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <inheritdoc cref="IMessage"/>
public abstract class MessageBase : OperResult<byte[]>, IMessage

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 采集返回消息

View File

@@ -12,7 +12,7 @@
using Newtonsoft.Json;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <inheritdoc/>
public class OperResult<T> : OperResult, IOperResult<T>

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// BCD格式化值

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 应用于多字节数据的解析或是生成格式<br />

View File

@@ -21,7 +21,7 @@ using Newtonsoft.Json.Converters;
#endif
using System.Text;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;

View File

@@ -18,7 +18,7 @@ using Newtonsoft.Json;
using System.Text;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 类型转换

View File

@@ -15,7 +15,7 @@ using System.Text;
using ThingsGateway.Foundation.Extension.Bool;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 将基数据类型转换为指定端的一个字节数组,

View File

@@ -12,7 +12,7 @@
using System.Text;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 所有数据转换类的静态辅助方法

View File

@@ -12,7 +12,7 @@
using System.Text;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// 常用转换

View File

@@ -11,7 +11,7 @@
#endregion
using System.Text;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// FileUtil
/// </summary>

View File

@@ -11,7 +11,7 @@
#endregion
using Newtonsoft.Json.Linq;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.Foundation.Core;
/// <summary>
/// JTokenUtil
/// </summary>

View File

@@ -17,7 +17,7 @@ global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using ThingsGateway.Foundation;
global using ThingsGateway.Foundation.Core;
global using ThingsGateway.Foundation.Http;
global using ThingsGateway.Foundation.Rpc;
global using ThingsGateway.Foundation.Serial;

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 注册为消息

View File

@@ -23,7 +23,9 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 消息通知类。内部全为弱引用。
@@ -31,8 +33,7 @@ namespace ThingsGateway.Foundation
public class AppMessenger
{
private static AppMessenger m_instance;
private readonly ReaderWriterLockSlim m_lockSlim = new ReaderWriterLockSlim();
private readonly Dictionary<string, List<MessageInstance>> m_tokenAndInstance = new Dictionary<string, List<MessageInstance>>();
private readonly ConcurrentDictionary<string, List<MessageInstance>> m_tokenAndInstance = new ConcurrentDictionary<string, List<MessageInstance>>();
/// <summary>
/// 默认单例实例
@@ -65,42 +66,38 @@ namespace ThingsGateway.Foundation
/// <summary>
/// 添加
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="token"></param>
/// <param name="messageInstance"></param>
/// <exception cref="MessageRegisteredException"></exception>
public void Add(string cancellationToken, MessageInstance messageInstance)
public void Add(string token, MessageInstance messageInstance)
{
using (var writeLock = new WriteLock(this.m_lockSlim))
if (this.m_tokenAndInstance.TryGetValue(token, out var value))
{
if (this.m_tokenAndInstance.ContainsKey(cancellationToken))
if (!this.AllowMultiple)
{
if (!this.AllowMultiple)
{
throw new MessageRegisteredException(TouchSocketCoreResource.TokenExisted.GetDescription(cancellationToken));
}
this.m_tokenAndInstance[cancellationToken].Add(messageInstance);
throw new MessageRegisteredException(TouchSocketCoreResource.TokenExisted.GetDescription(token));
}
else
{
this.m_tokenAndInstance.Add(cancellationToken, new List<MessageInstance>()
value.Add(messageInstance);
}
else
{
this.m_tokenAndInstance.TryAdd(token, new List<MessageInstance>()
{
messageInstance
});
}
}
}
/// <summary>
/// 判断能否触发该消息,意味着该消息是否已经注册。
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="token"></param>
/// <returns></returns>
public bool CanSendMessage(string cancellationToken)
public bool CanSendMessage(string token)
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
return this.m_tokenAndInstance.ContainsKey(cancellationToken);
}
return this.m_tokenAndInstance.ContainsKey(token);
}
/// <summary>
@@ -108,34 +105,25 @@ namespace ThingsGateway.Foundation
/// </summary>
public void Clear()
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
this.m_tokenAndInstance.Clear();
}
this.m_tokenAndInstance.Clear();
}
/// <summary>
/// 获取所有消息
/// </summary>
/// <returns></returns>
public string[] GetAllMessage()
public IEnumerable<string> GetAllMessage()
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
return this.m_tokenAndInstance.Keys.ToArray();
}
return this.m_tokenAndInstance.Keys;
}
/// <summary>
/// 移除
/// </summary>
/// <param name="cancellationToken"></param>
public void Remove(string cancellationToken)
/// <param name="token"></param>
public void Remove(string token)
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
this.m_tokenAndInstance.Remove(cancellationToken);
}
this.m_tokenAndInstance.TryRemove(token, out _);
}
/// <summary>
@@ -144,132 +132,105 @@ namespace ThingsGateway.Foundation
/// <param name="messageObject"></param>
public void Remove(IMessageObject messageObject)
{
using (var writeLock = new WriteLock(this.m_lockSlim))
{
var key = new List<string>();
var key = new List<string>();
foreach (var item in this.m_tokenAndInstance.Keys)
foreach (var item in this.m_tokenAndInstance.Keys)
{
foreach (var item2 in this.m_tokenAndInstance[item].ToArray())
{
foreach (var item2 in this.m_tokenAndInstance[item].ToArray())
if (messageObject == item2.MessageObject)
{
if (messageObject == item2.MessageObject)
this.m_tokenAndInstance[item].Remove(item2);
if (this.m_tokenAndInstance[item].Count == 0)
{
this.m_tokenAndInstance[item].Remove(item2);
if (this.m_tokenAndInstance[item].Count == 0)
{
key.Add(item);
}
key.Add(item);
}
}
}
}
foreach (var item in key)
{
this.m_tokenAndInstance.Remove(item);
}
foreach (var item in key)
{
this.m_tokenAndInstance.TryRemove(item, out _);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="token"></param>
/// <param name="parameters"></param>
/// <exception cref="MessageNotFoundException"></exception>
public Task SendAsync(string cancellationToken, params object[] parameters)
public async Task SendAsync(string token, params object[] parameters)
{
return Task.Run(() =>
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
if (this.m_tokenAndInstance.TryGetValue(cancellationToken, out var list))
{
var clear = new List<MessageInstance>();
if (this.m_tokenAndInstance.TryGetValue(token, out var list))
{
var clear = new List<MessageInstance>();
foreach (var item in list)
{
if (!item.Info.IsStatic && !item.WeakReference.TryGetTarget(out _))
{
clear.Add(item);
continue;
}
try
{
item.Invoke(item.MessageObject, parameters);
}
catch
{
}
}
foreach (var item in list)
{
if (!item.Info.IsStatic && !item.WeakReference.TryGetTarget(out _))
{
clear.Add(item);
continue;
}
await item.InvokeAsync(item.MessageObject, parameters);
}
foreach (var item in clear)
{
list.Remove(item);
}
}
else
{
throw new MessageNotFoundException(TouchSocketCoreResource.MessageNotFound.GetDescription(cancellationToken));
}
}
});
foreach (var item in clear)
{
list.Remove(item);
}
}
else
{
throw new MessageNotFoundException(TouchSocketCoreResource.MessageNotFound.GetDescription(token));
}
}
/// <summary>
/// 发送消息,当多播时,只返回最后一个返回值
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="cancellationToken"></param>
/// <param name="token"></param>
/// <param name="parameters"></param>
/// <returns></returns>
/// <exception cref="MessageNotFoundException"></exception>
public Task<T> SendAsync<T>(string cancellationToken, params object[] parameters)
public async Task<T> SendAsync<T>(string token, params object[] parameters)
{
return Task.Run(() =>
{
using (var readLock = new ReadLock(this.m_lockSlim))
{
if (this.m_tokenAndInstance.TryGetValue(cancellationToken, out var list))
{
T result = default;
var clear = new List<MessageInstance>();
for (var i = 0; i < list.Count; i++)
{
var item = list[i];
if (!item.Info.IsStatic && !item.WeakReference.TryGetTarget(out _))
{
clear.Add(item);
continue;
}
if (this.m_tokenAndInstance.TryGetValue(token, out var list))
{
T result = default;
var clear = new List<MessageInstance>();
for (var i = 0; i < list.Count; i++)
{
var item = list[i];
if (!item.Info.IsStatic && !item.WeakReference.TryGetTarget(out _))
{
clear.Add(item);
continue;
}
try
{
if (i == list.Count - 1)
{
result = (T)item.Invoke(item.MessageObject, parameters);
}
else
{
item.Invoke(item.MessageObject, parameters);
}
}
catch
{
}
}
if (i == list.Count - 1)
{
result = await item.InvokeAsync<T>(item.MessageObject, parameters);
}
else
{
await item.InvokeAsync<T>(item.MessageObject, parameters);
}
}
foreach (var item in clear)
{
list.Remove(item);
}
return result;
}
else
{
throw new MessageNotFoundException(TouchSocketCoreResource.MessageNotFound.GetDescription(cancellationToken));
}
}
});
foreach (var item in clear)
{
list.Remove(item);
}
return result;
}
else
{
throw new MessageNotFoundException(TouchSocketCoreResource.MessageNotFound.GetDescription(token));
}
}
}
}

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Reflection;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// AppMessengerExtensions

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 限定消息的接口

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Reflection;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// MessageInstance

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 缓存实体

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// CacheExtensions

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 缓存键值

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 缓存实体接口

View File

@@ -25,7 +25,7 @@
using System.Collections;
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 一个简单的内存缓存

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 安全双向字典

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Collections;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 线程安全的List其基本操作和List一致。

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 三元组合

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 智能安全队列

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 队列数据

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 触发器队列

View File

@@ -25,7 +25,7 @@
using System.Collections.Specialized;
using System.Diagnostics;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// IgnoreCaseNameValueCollection

View File

@@ -25,7 +25,7 @@
using System.Collections.Specialized;
using System.Diagnostics;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// NameValueCollectionDebugView

View File

@@ -23,7 +23,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 运行配置类

View File

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// <see cref="decimal"/>与字节数组转换

View File

@@ -24,7 +24,7 @@
//------------------------------------------------------------------------------
using System.Runtime.CompilerServices;
namespace ThingsGateway.Foundation
namespace ThingsGateway.Foundation.Core
{
/// <summary>
/// 具有释放的对象。

Some files were not shown because too many files have changed in this diff Show More