Compare commits
	
		
			59 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c27dde085e | ||
| 
						 | 
					d26cc308c0 | ||
| 
						 | 
					fb1efdf290 | ||
| 
						 | 
					3c99f2a472 | ||
| 
						 | 
					affe9a44e0 | ||
| 
						 | 
					43730fa519 | ||
| 
						 | 
					d39aa22b09 | ||
| 
						 | 
					e232a6b6ea | ||
| 
						 | 
					71ebb36fe9 | ||
| 
						 | 
					78a0b86327 | ||
| 
						 | 
					2636c16a97 | ||
| 
						 | 
					fd77c0242d | ||
| 
						 | 
					e74819a900 | ||
| 
						 | 
					9b7f696c9b | ||
| 
						 | 
					0230d614e7 | ||
| 
						 | 
					252d99ad78 | ||
| 
						 | 
					1ffc200350 | ||
| 
						 | 
					807d89b2b2 | ||
| 
						 | 
					4013afa1f1 | ||
| 
						 | 
					a580927ceb | ||
| 
						 | 
					bf2cf52034 | ||
| 
						 | 
					81bb8b7c31 | ||
| 
						 | 
					a825007fb5 | ||
| 
						 | 
					988124d96a | ||
| 
						 | 
					f0de815296 | ||
| 
						 | 
					0e2d58c887 | ||
| 
						 | 
					b155382626 | ||
| 
						 | 
					f362d740af | ||
| 
						 | 
					4a85e31a4f | ||
| 
						 | 
					302c270ad5 | ||
| 
						 | 
					3c1517d0f3 | ||
| 
						 | 
					f9fb222044 | ||
| 
						 | 
					e8edc02ba3 | ||
| 
						 | 
					95a44e3053 | ||
| 
						 | 
					74a9fe9a87 | ||
| 
						 | 
					4d03f9ea1a | ||
| 
						 | 
					67c96ca991 | ||
| 
						 | 
					88fb793c68 | ||
| 
						 | 
					d6d02d8cc5 | ||
| 
						 | 
					c5a3f8e2e3 | ||
| 
						 | 
					27e8653a1a | ||
| 
						 | 
					863beda82c | ||
| 
						 | 
					bac84c3ecd | ||
| 
						 | 
					2fca2ad9f8 | ||
| 
						 | 
					dd75286fe0 | ||
| 
						 | 
					7f91792cf1 | ||
| 
						 | 
					0e0ccad311 | ||
| 
						 | 
					0691f72e67 | ||
| 
						 | 
					7e38a51720 | ||
| 
						 | 
					34ca8243a3 | ||
| 
						 | 
					112fea7632 | ||
| 
						 | 
					378763e4ee | ||
| 
						 | 
					517bd0394d | ||
| 
						 | 
					70adb97fb5 | ||
| 
						 | 
					623d44cabe | ||
| 
						 | 
					0d479ca00b | ||
| 
						 | 
					8bc49ef437 | ||
| 
						 | 
					f83fcec786 | ||
| 
						 | 
					93690ce40d | 
@@ -5,3 +5,99 @@ dotnet_diagnostic.CA1848.severity = none
 | 
			
		||||
 | 
			
		||||
# CA2254: 模板应为静态表达式
 | 
			
		||||
dotnet_diagnostic.CA2254.severity = suggestion
 | 
			
		||||
 | 
			
		||||
[*.cs]
 | 
			
		||||
#### 命名样式 ####
 | 
			
		||||
 | 
			
		||||
# 命名规则
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
 | 
			
		||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
 | 
			
		||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
 | 
			
		||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
 | 
			
		||||
 | 
			
		||||
# 符号规范
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_kinds = interface
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
 | 
			
		||||
dotnet_naming_symbols.interface.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
 | 
			
		||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
 | 
			
		||||
dotnet_naming_symbols.types.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
 | 
			
		||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
 | 
			
		||||
dotnet_naming_symbols.non_field_members.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
# 命名样式
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.begins_with_i.required_prefix = I
 | 
			
		||||
dotnet_naming_style.begins_with_i.required_suffix = 
 | 
			
		||||
dotnet_naming_style.begins_with_i.word_separator = 
 | 
			
		||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.pascal_case.required_prefix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.required_suffix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.word_separator = 
 | 
			
		||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.pascal_case.required_prefix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.required_suffix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.word_separator = 
 | 
			
		||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
[*.vb]
 | 
			
		||||
#### 命名样式 ####
 | 
			
		||||
 | 
			
		||||
# 命名规则
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
 | 
			
		||||
dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
 | 
			
		||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
 | 
			
		||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
 | 
			
		||||
 | 
			
		||||
# 符号规范
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_kinds = interface
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
 | 
			
		||||
dotnet_naming_symbols.interface.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
 | 
			
		||||
dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
 | 
			
		||||
dotnet_naming_symbols.类型.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
 | 
			
		||||
dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
 | 
			
		||||
dotnet_naming_symbols.非字段成员.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
# 命名样式
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.以_i_开始.required_prefix = I
 | 
			
		||||
dotnet_naming_style.以_i_开始.required_suffix = 
 | 
			
		||||
dotnet_naming_style.以_i_开始.word_separator = 
 | 
			
		||||
dotnet_naming_style.以_i_开始.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_prefix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_suffix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.word_separator = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_prefix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_suffix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.word_separator = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<Project>
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<Version>3.0.0.6</Version>
 | 
			
		||||
		<Version>3.0.0.23</Version>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
		<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
		<Authors>Diego</Authors>
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            Messages.Add((LogLevel.Error,
 | 
			
		||||
            $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 错误:{ex.Message}"));
 | 
			
		||||
            $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 错误:{ex}"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
@@ -126,7 +126,7 @@ public abstract class DriverDebugUIBase : ComponentBase, IDisposable
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            Messages.Add((LogLevel.Error,
 | 
			
		||||
            $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 写入前失败:{ex.Message}"));
 | 
			
		||||
            $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 写入前失败:{ex}"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ public partial class DriverDebugUIPage : DriverDebugUIBase
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex.Message));
 | 
			
		||||
                    Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,15 @@ public partial class MainLayout
 | 
			
		||||
        var dataStringPro =
 | 
			
		||||
"""
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "Title": "Melsec",
 | 
			
		||||
    "Children": [
 | 
			
		||||
      {
 | 
			
		||||
        "Href": "/QnA3E_Binary",
 | 
			
		||||
        "Title": "QnA3E_Binary"
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Title": "ABCIP",
 | 
			
		||||
    "Children": [
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,14 @@
 | 
			
		||||
		<DefineConstants>Pro</DefineConstants>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
	<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor.cs" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor.cs" />
 | 
			
		||||
		<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor" />
 | 
			
		||||
		<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Melsec\ThingsGateway.Foundation.Adapter.Melsec.csproj" />
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		
 | 
			
		||||
		<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor.cs" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor.cs" />
 | 
			
		||||
		<Content Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor" />
 | 
			
		||||
@@ -107,12 +115,20 @@
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
	<ItemGroup >
 | 
			
		||||
		<!--<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" />
 | 
			
		||||
		<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="*" />
 | 
			
		||||
		<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCDA" Version="*" />
 | 
			
		||||
		<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCUA" Version="*" />
 | 
			
		||||
		<PackageReference Include="ThingsGateway.Foundation.Adapter.Siemens" Version="*" />-->
 | 
			
		||||
		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj" />
 | 
			
		||||
		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" />
 | 
			
		||||
		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj" />
 | 
			
		||||
		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" />
 | 
			
		||||
		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj" />
 | 
			
		||||
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	<ItemGroup >
 | 
			
		||||
		<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
@@ -124,10 +140,6 @@
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
	  <Folder Include="Pages\Mqtt\" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
	  <Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor" Link="Pages\Mqtt\MqttClientDebugPage.razor" />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,12 @@
 | 
			
		||||
<Project>
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<Version>3.0.0.6</Version>
 | 
			
		||||
		<Version>3.0.0.23</Version>
 | 
			
		||||
		<GenerateDocumentationFile>True</GenerateDocumentationFile>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
		<Description>
 | 
			
		||||
			ThingsGateway.Foundation是工业设备通讯类库,归属于ThingsGateway边缘网关项目,说明文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
		</Description>
 | 
			
		||||
		<Authors>Diego</Authors>
 | 
			
		||||
		<Product>ThingsGateway</Product>
 | 
			
		||||
		<Copyright>© 2023-present Diego</Copyright>
 | 
			
		||||
@@ -16,7 +19,6 @@
 | 
			
		||||
		<PackageReadmeFile>README.md</PackageReadmeFile>
 | 
			
		||||
		<PackageIcon>icon.png</PackageIcon>
 | 
			
		||||
		<IncludeSymbols>true</IncludeSymbols>
 | 
			
		||||
		<SymbolPackageFormat>snupkg</SymbolPackageFormat>
 | 
			
		||||
		<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
 | 
			
		||||
		<PackageProjectUrl>https://diego2098.gitee.io/thingsgateway-docs/</PackageProjectUrl>
 | 
			
		||||
		<PackageTags>ThingsGateway;Diego;dotNET China;Blazor;设备采集;边缘网关</PackageTags>
 | 
			
		||||
@@ -42,5 +44,10 @@
 | 
			
		||||
		</None>
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup Condition="'$(Configuration)' == 'Release'">
 | 
			
		||||
		<DebugSymbols>True</DebugSymbols>
 | 
			
		||||
		<DebugType>Embedded</DebugType>
 | 
			
		||||
		<EmbedAllSources>True</EmbedAllSources>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
	
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -444,7 +444,7 @@ public class DLT645_2007 : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
 | 
			
		||||
            if (Station.IsNullOrEmpty()) Station = string.Empty;
 | 
			
		||||
            if (Station.Length < 12) Station = Station.PadLeft(12, '0');
 | 
			
		||||
            string str = $"04000C{(level + 1):D2}";
 | 
			
		||||
            string str = $"04000C{level + 1:D2}";
 | 
			
		||||
 | 
			
		||||
            var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WritePassword,
 | 
			
		||||
                str.ByHexStringToBytes().Reverse().ToArray()
 | 
			
		||||
 
 | 
			
		||||
@@ -92,15 +92,15 @@ public class DLT645_2007Address : DeviceAddressBase
 | 
			
		||||
        StringBuilder stringGeter = new();
 | 
			
		||||
        if (Station.Length > 0)
 | 
			
		||||
        {
 | 
			
		||||
            stringGeter.Append("s=" + Station.Reverse().ToArray().ToHexString() + ";");
 | 
			
		||||
            stringGeter.Append($"s={Station.Reverse().ToArray().ToHexString()};");
 | 
			
		||||
        }
 | 
			
		||||
        if (DataId.Length > 0)
 | 
			
		||||
        {
 | 
			
		||||
            stringGeter.Append(DataId.Reverse().ToArray().ToHexString() + ";");
 | 
			
		||||
            stringGeter.Append($"{DataId.Reverse().ToArray().ToHexString()};");
 | 
			
		||||
        }
 | 
			
		||||
        if (!Reverse)
 | 
			
		||||
        {
 | 
			
		||||
            stringGeter.Append("s=" + Reverse.ToString() + ";");
 | 
			
		||||
            stringGeter.Append($"s={Reverse.ToString()};");
 | 
			
		||||
        }
 | 
			
		||||
        return stringGeter.ToString();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -134,7 +134,7 @@ public class DLT645_2007DataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter
 | 
			
		||||
 | 
			
		||||
            if ((response[headCodeIndex + 8] != send[sendHeadCodeIndex + 8] + 0x80))//控制码不符合时,返回错误
 | 
			
		||||
            {
 | 
			
		||||
                request.Message = "返回控制码:" + $"0x{response[headCodeIndex + 8]:X2},请求控制码:" + $"0x{send[sendHeadCodeIndex + 8]:X2},不符合规则";
 | 
			
		||||
                request.Message = $"返回控制码:0x{response[headCodeIndex + 8]:X2},请求控制码:0x{send[sendHeadCodeIndex + 8]:X2},不符合规则";
 | 
			
		||||
                request.ErrorCode = 999;
 | 
			
		||||
                return FilterResult.Success;
 | 
			
		||||
            }
 | 
			
		||||
@@ -146,7 +146,7 @@ public class DLT645_2007DataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter
 | 
			
		||||
            {
 | 
			
		||||
                byte byte1 = (byte)(response[headCodeIndex + 10] - 0x33);
 | 
			
		||||
                var error = DLT645Helper.Get2007ErrorMessage(byte1);
 | 
			
		||||
                request.Message = "异常控制码:" + $"0x{response[headCodeIndex + 8]:X2},错误信息:{error}";
 | 
			
		||||
                request.Message = $"异常控制码:0x{response[headCodeIndex + 8]:X2},错误信息:{error}";
 | 
			
		||||
                request.ErrorCode = 999;
 | 
			
		||||
                return FilterResult.Success;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,15 +20,12 @@ public class DLT645_2007Message : MessageBase, IMessage
 | 
			
		||||
    public override int HeadBytesLength => -1;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] head)
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] heads)
 | 
			
		||||
    {
 | 
			
		||||
        BodyLength = -1;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void SendBytesThen()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
 | 
			
		||||
 | 
			
		||||
internal static class PackHelper
 | 
			
		||||
 
 | 
			
		||||
@@ -1,442 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<doc>
 | 
			
		||||
    <assembly>
 | 
			
		||||
        <name>ThingsGateway.Foundation.Adapter.DLT645</name>
 | 
			
		||||
    </assembly>
 | 
			
		||||
    <members>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.DataInfo">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析参数
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.ByteLength">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析长度
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.Digtal">
 | 
			
		||||
            <summary>
 | 
			
		||||
            小数位
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.IsSigned">
 | 
			
		||||
            <summary>
 | 
			
		||||
            有符号解析
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDataInfos(System.Byte[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            获取返回的解析信息
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="buffer"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDLT645_2007Command(System.String,System.Int32,System.Byte,System.String,System.Byte[],System.String[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            获取DLT645报文
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.#ctor(ThingsGateway.Foundation.Serial.SerialSession)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="serialSession"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.EnableFEHead">
 | 
			
		||||
            <summary>
 | 
			
		||||
            增加FE FE FE FE的报文头部
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.OperCode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入需操作员代码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Password">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入密码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Station">
 | 
			
		||||
            <summary>
 | 
			
		||||
            通讯地址BCD码,一般应该是12个字符
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.GetAddressDescription">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.SetDataAdapter">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            广播校时
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="dateTime"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            冻结
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="dateTime"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadDeviceStationAsync(System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取通信地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            修改波特率
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="baudRate"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            更新通信地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="station"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            修改密码
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="level"></param>
 | 
			
		||||
            <param name="oldPassword"></param>
 | 
			
		||||
            <param name="newPassword"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.ControlCode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            控制码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Read">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读数据
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadSub">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读后续数据
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadStation">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读站号
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Write">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写数据
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteStation">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写站号
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.BroadcastTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            广播校时
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Freeze">
 | 
			
		||||
            <summary>
 | 
			
		||||
            冻结
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteBaudRate">
 | 
			
		||||
            <summary>
 | 
			
		||||
            更新波特率
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WritePassword">
 | 
			
		||||
            <summary>
 | 
			
		||||
            更新密码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007Address
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.UInt16)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.DataId">
 | 
			
		||||
            <summary>
 | 
			
		||||
            数据标识
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Reverse">
 | 
			
		||||
            <summary>
 | 
			
		||||
            反转解析
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Station">
 | 
			
		||||
            <summary>
 | 
			
		||||
            站号信息
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Parse(System.String,System.Int32)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ParseFrom(System.String,System.Int32)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="address"></param>
 | 
			
		||||
            <param name="length"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ToString">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.#ctor(ThingsGateway.Foundation.Core.EndianType)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToDouble(System.Byte[],System.Int32)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645协议转换double
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="buffer">带数据项标识</param>
 | 
			
		||||
            <param name="offset"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[],System.Int32,System.Int32)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007DataHandleAdapter
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.EnableFEHead">
 | 
			
		||||
            <summary>
 | 
			
		||||
            增加FE FE FE FE的报文头部
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.PackCommand(System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.GetInstance">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message,System.Byte[],System.Byte[],System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.#ctor(ThingsGateway.Foundation.Core.TcpClient)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DLT645_2007
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="tcpClient"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.EnableFEHead">
 | 
			
		||||
            <summary>
 | 
			
		||||
            增加FE FE FE FE的报文头部
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.OperCode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入需操作员代码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Password">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入密码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Station">
 | 
			
		||||
            <summary>
 | 
			
		||||
            通讯地址BCD码,一般应该是12个字符
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.GetAddressDescription">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.SetDataAdapter">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            广播校时
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="dateTime"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            冻结
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="dateTime"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadDeviceStationAsync(System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取通信地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            修改波特率
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="baudRate"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            更新通信地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="station"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            修改密码
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="level"></param>
 | 
			
		||||
            <param name="oldPassword"></param>
 | 
			
		||||
            <param name="newPassword"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.HeadBytesLength">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.CheckHeadBytes(System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.SendBytesThen">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
    </members>
 | 
			
		||||
</doc>
 | 
			
		||||
@@ -147,15 +147,15 @@ public class ModbusAddress : DeviceAddressBase
 | 
			
		||||
        StringBuilder stringGeter = new();
 | 
			
		||||
        if (Station > 0)
 | 
			
		||||
        {
 | 
			
		||||
            stringGeter.Append("s=" + Station.ToString() + ";");
 | 
			
		||||
            stringGeter.Append($"s={Station.ToString()};");
 | 
			
		||||
        }
 | 
			
		||||
        if (WriteFunction > 0)
 | 
			
		||||
        {
 | 
			
		||||
            stringGeter.Append("w=" + WriteFunction.ToString() + ";");
 | 
			
		||||
            stringGeter.Append($"w={WriteFunction.ToString()};");
 | 
			
		||||
        }
 | 
			
		||||
        if (!string.IsNullOrEmpty(SocketId))
 | 
			
		||||
        {
 | 
			
		||||
            stringGeter.Append("id=" + SocketId + ";");
 | 
			
		||||
            stringGeter.Append($"id={SocketId};");
 | 
			
		||||
        }
 | 
			
		||||
        stringGeter.Append(GetFunctionString(ReadFunction) + (AddressStart + 1).ToString());
 | 
			
		||||
        return stringGeter.ToString();
 | 
			
		||||
 
 | 
			
		||||
@@ -117,7 +117,7 @@ internal class ModbusHelper
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[], FilterResult>(ex.Message) { Content2 = FilterResult.Success };
 | 
			
		||||
            return new OperResult<byte[], FilterResult>(ex) { Content2 = FilterResult.Success };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -165,7 +165,7 @@ internal class ModbusHelper
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -185,7 +185,7 @@ internal class ModbusHelper
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -207,7 +207,7 @@ internal class ModbusHelper
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -244,7 +244,7 @@ internal class ModbusHelper
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -296,7 +296,7 @@ internal class ModbusHelper
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,15 +20,12 @@ public class ModbusRtuMessage : MessageBase, IMessage
 | 
			
		||||
    public override int HeadBytesLength => -1;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] head)
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] heads)
 | 
			
		||||
    {
 | 
			
		||||
        BodyLength = -1;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void SendBytesThen()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -24,7 +24,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, OperResult> WriteData;
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, Task<OperResult>> WriteData;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 继电器
 | 
			
		||||
@@ -101,62 +101,76 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
        return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EasyLock easyLock = new();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        ModbusAddress mAddress;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
        if (MulStation)
 | 
			
		||||
        {
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (Station != mAddress.Station)
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
 | 
			
		||||
            ModbusAddress mAddress;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult<byte[]>("地址错误");
 | 
			
		||||
                mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
            }
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult<byte[]>(ex);
 | 
			
		||||
            }
 | 
			
		||||
            if (MulStation)
 | 
			
		||||
            {
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Station != mAddress.Station)
 | 
			
		||||
                {
 | 
			
		||||
                    return new OperResult<byte[]>("地址错误");
 | 
			
		||||
                }
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
            int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
 | 
			
		||||
            switch (mAddress.ReadFunction)
 | 
			
		||||
            {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    byte[] bytes0 = new byte[len];
 | 
			
		||||
                    ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer01ByteBlock.Read(bytes0);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes0);
 | 
			
		||||
                case 2:
 | 
			
		||||
                    byte[] bytes1 = new byte[len];
 | 
			
		||||
                    ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer02ByteBlock.Read(bytes1);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes1);
 | 
			
		||||
                case 3:
 | 
			
		||||
 | 
			
		||||
                    byte[] bytes3 = new byte[len];
 | 
			
		||||
                    ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer03ByteBlock.Read(bytes3);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes3);
 | 
			
		||||
                case 4:
 | 
			
		||||
                    byte[] bytes4 = new byte[len];
 | 
			
		||||
                    ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer04ByteBlock.Read(bytes4);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes4);
 | 
			
		||||
            }
 | 
			
		||||
            return new OperResult<byte[]>("功能码错误");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
        int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
 | 
			
		||||
        switch (mAddress.ReadFunction)
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            case 1:
 | 
			
		||||
                byte[] bytes0 = new byte[len];
 | 
			
		||||
                ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer01ByteBlock.Read(bytes0);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes0);
 | 
			
		||||
            case 2:
 | 
			
		||||
                byte[] bytes1 = new byte[len];
 | 
			
		||||
                ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer02ByteBlock.Read(bytes1);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes1);
 | 
			
		||||
            case 3:
 | 
			
		||||
 | 
			
		||||
                byte[] bytes3 = new byte[len];
 | 
			
		||||
                ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer03ByteBlock.Read(bytes3);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes3);
 | 
			
		||||
            case 4:
 | 
			
		||||
                byte[] bytes4 = new byte[len];
 | 
			
		||||
                ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer04ByteBlock.Read(bytes4);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes4);
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
        }
 | 
			
		||||
        return new OperResult<byte[]>("功能码错误");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -173,87 +187,108 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
        SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        ModbusAddress mAddress;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult(ex);
 | 
			
		||||
        }
 | 
			
		||||
        if (MulStation)
 | 
			
		||||
        {
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (Station != mAddress.Station)
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
            ModbusAddress mAddress;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult("地址错误");
 | 
			
		||||
                mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
            }
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult(ex);
 | 
			
		||||
            }
 | 
			
		||||
            if (MulStation)
 | 
			
		||||
            {
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Station != mAddress.Station)
 | 
			
		||||
                {
 | 
			
		||||
                    return new OperResult("地址错误");
 | 
			
		||||
                }
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
            }
 | 
			
		||||
            var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
            switch (mAddress.ReadFunction)
 | 
			
		||||
            {
 | 
			
		||||
                case 3:
 | 
			
		||||
                    ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer03ByteBlock.Write(value);
 | 
			
		||||
                    return OperResult.CreateSuccessResult();
 | 
			
		||||
                case 4:
 | 
			
		||||
                    ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer04ByteBlock.Write(value);
 | 
			
		||||
                    return OperResult.CreateSuccessResult();
 | 
			
		||||
            }
 | 
			
		||||
            return new OperResult("功能码错误");
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
        switch (mAddress.ReadFunction)
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            case 3:
 | 
			
		||||
                ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer03ByteBlock.Write(value);
 | 
			
		||||
                return OperResult.CreateSuccessResult();
 | 
			
		||||
            case 4:
 | 
			
		||||
                ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer04ByteBlock.Write(value);
 | 
			
		||||
                return OperResult.CreateSuccessResult();
 | 
			
		||||
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
        }
 | 
			
		||||
        return new OperResult("功能码错误");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        ModbusAddress mAddress;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return (new OperResult(ex));
 | 
			
		||||
        }
 | 
			
		||||
        if (MulStation)
 | 
			
		||||
        {
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (Station != mAddress.Station)
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
            ModbusAddress mAddress;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (new OperResult("地址错误"));
 | 
			
		||||
                mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
            }
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return (new OperResult(ex));
 | 
			
		||||
            }
 | 
			
		||||
            if (MulStation)
 | 
			
		||||
            {
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Station != mAddress.Station)
 | 
			
		||||
                {
 | 
			
		||||
                    return (new OperResult("地址错误"));
 | 
			
		||||
                }
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
            switch (mAddress.ReadFunction)
 | 
			
		||||
            {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                    return (OperResult.CreateSuccessResult());
 | 
			
		||||
                case 2:
 | 
			
		||||
                    ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                    return (OperResult.CreateSuccessResult());
 | 
			
		||||
            }
 | 
			
		||||
            return new OperResult("功能码错误");
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
        switch (mAddress.ReadFunction)
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            case 1:
 | 
			
		||||
                ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                return (OperResult.CreateSuccessResult());
 | 
			
		||||
            case 2:
 | 
			
		||||
                ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                return (OperResult.CreateSuccessResult());
 | 
			
		||||
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
        }
 | 
			
		||||
        return new OperResult("功能码错误");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -267,12 +302,13 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
    {
 | 
			
		||||
        return Task.FromResult(Write(address, value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void Received(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    protected override async Task Received(SerialSession client, ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            var requestInfo = e.RequestInfo;
 | 
			
		||||
            //接收外部报文
 | 
			
		||||
            if (requestInfo is ModbusSerialServerMessage modbusServerMessage)
 | 
			
		||||
            {
 | 
			
		||||
@@ -312,7 +348,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
                        if (WriteData != null)
 | 
			
		||||
                        {
 | 
			
		||||
                            // 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
 | 
			
		||||
                            if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
 | 
			
		||||
                            if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
 | 
			
		||||
                            {
 | 
			
		||||
                                var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
@@ -349,7 +385,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
                        if (WriteData != null)
 | 
			
		||||
                        {
 | 
			
		||||
 | 
			
		||||
                            if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
 | 
			
		||||
                            if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
 | 
			
		||||
                            {
 | 
			
		||||
                                var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
@@ -408,13 +444,9 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
 | 
			
		||||
    private void Init(ModbusAddress mAddress)
 | 
			
		||||
    {
 | 
			
		||||
        if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
        ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
        ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
        ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ public class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesTcpDataHandle
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,14 +30,11 @@ public class ModbusSerialServerMessage : MessageBase, IMessage
 | 
			
		||||
    public override int HeadBytesLength => -1;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] head)
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] heads)
 | 
			
		||||
    {
 | 
			
		||||
        BodyLength = -1;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void SendBytesThen()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -23,10 +23,10 @@ public class ModbusTcpMessage : MessageBase, IMessage
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool IsCheckMessageId { get; set; } = false;
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] head)
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] heads)
 | 
			
		||||
    {
 | 
			
		||||
        if (head == null || head.Length <= 0) return false;
 | 
			
		||||
        HeadBytes = head;
 | 
			
		||||
        if (heads == null || heads.Length <= 0) return false;
 | 
			
		||||
        HeadBytes = heads;
 | 
			
		||||
 | 
			
		||||
        int num = (HeadBytes[4] * 256) + HeadBytes[5];
 | 
			
		||||
        BodyLength = num;
 | 
			
		||||
 
 | 
			
		||||
@@ -84,15 +84,6 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    protected override void Connecting(SocketClient client, ConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override void SetDataAdapter(object socketClient = null)
 | 
			
		||||
@@ -195,7 +186,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                var item = commandResult.Content;
 | 
			
		||||
                if (FrameTime != 0)
 | 
			
		||||
                    Thread.Sleep(FrameTime);
 | 
			
		||||
                var WaitingClientEx = client.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
                var WaitingClientEx = client.CreateWaitingClient(new() {  });
 | 
			
		||||
                var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
 | 
			
		||||
                return (MessageBase)result.RequestInfo;
 | 
			
		||||
            }
 | 
			
		||||
@@ -222,7 +213,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
 | 
			
		||||
                var item = commandResult.Content;
 | 
			
		||||
                await Task.Delay(FrameTime, cancellationToken);
 | 
			
		||||
                var WaitingClientEx = client.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
                var WaitingClientEx = client.CreateWaitingClient(new() {  });
 | 
			
		||||
                var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
 | 
			
		||||
                return (MessageBase)result.RequestInfo;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, OperResult> WriteData;
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, Task<OperResult>> WriteData;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 继电器
 | 
			
		||||
@@ -104,62 +104,75 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
        return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EasyLock easyLock = new();
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        ModbusAddress mAddress;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
        if (MulStation)
 | 
			
		||||
        {
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (Station != mAddress.Station)
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
 | 
			
		||||
            ModbusAddress mAddress;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult<byte[]>("地址错误");
 | 
			
		||||
                mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
            }
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult<byte[]>(ex);
 | 
			
		||||
            }
 | 
			
		||||
            if (MulStation)
 | 
			
		||||
            {
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Station != mAddress.Station)
 | 
			
		||||
                {
 | 
			
		||||
                    return new OperResult<byte[]>("地址错误");
 | 
			
		||||
                }
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
            int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
 | 
			
		||||
            switch (mAddress.ReadFunction)
 | 
			
		||||
            {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    byte[] bytes0 = new byte[len];
 | 
			
		||||
                    ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer01ByteBlock.Read(bytes0);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes0);
 | 
			
		||||
                case 2:
 | 
			
		||||
                    byte[] bytes1 = new byte[len];
 | 
			
		||||
                    ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer02ByteBlock.Read(bytes1);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes1);
 | 
			
		||||
                case 3:
 | 
			
		||||
 | 
			
		||||
                    byte[] bytes3 = new byte[len];
 | 
			
		||||
                    ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer03ByteBlock.Read(bytes3);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes3);
 | 
			
		||||
                case 4:
 | 
			
		||||
                    byte[] bytes4 = new byte[len];
 | 
			
		||||
                    ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer04ByteBlock.Read(bytes4);
 | 
			
		||||
                    return OperResult.CreateSuccessResult(bytes4);
 | 
			
		||||
            }
 | 
			
		||||
            return new OperResult<byte[]>("功能码错误");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
        int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
 | 
			
		||||
        switch (mAddress.ReadFunction)
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            case 1:
 | 
			
		||||
                byte[] bytes0 = new byte[len];
 | 
			
		||||
                ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer01ByteBlock.Read(bytes0);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes0);
 | 
			
		||||
            case 2:
 | 
			
		||||
                byte[] bytes1 = new byte[len];
 | 
			
		||||
                ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer02ByteBlock.Read(bytes1);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes1);
 | 
			
		||||
            case 3:
 | 
			
		||||
 | 
			
		||||
                byte[] bytes3 = new byte[len];
 | 
			
		||||
                ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer03ByteBlock.Read(bytes3);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes3);
 | 
			
		||||
            case 4:
 | 
			
		||||
                byte[] bytes4 = new byte[len];
 | 
			
		||||
                ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer04ByteBlock.Read(bytes4);
 | 
			
		||||
                return OperResult.CreateSuccessResult(bytes4);
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
        }
 | 
			
		||||
        return new OperResult<byte[]>("功能码错误");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -193,84 +206,104 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        ModbusAddress mAddress;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult(ex);
 | 
			
		||||
        }
 | 
			
		||||
        if (MulStation)
 | 
			
		||||
        {
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (Station != mAddress.Station)
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
            ModbusAddress mAddress;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult("地址错误");
 | 
			
		||||
                mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
            }
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return new OperResult(ex);
 | 
			
		||||
            }
 | 
			
		||||
            if (MulStation)
 | 
			
		||||
            {
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Station != mAddress.Station)
 | 
			
		||||
                {
 | 
			
		||||
                    return new OperResult("地址错误");
 | 
			
		||||
                }
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
            }
 | 
			
		||||
            var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
            switch (mAddress.ReadFunction)
 | 
			
		||||
            {
 | 
			
		||||
                case 3:
 | 
			
		||||
                    ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer03ByteBlock.Write(value);
 | 
			
		||||
                    return OperResult.CreateSuccessResult();
 | 
			
		||||
                case 4:
 | 
			
		||||
                    ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                    ModbusServer04ByteBlock.Write(value);
 | 
			
		||||
                    return OperResult.CreateSuccessResult();
 | 
			
		||||
            }
 | 
			
		||||
            return new OperResult("功能码错误");
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
 | 
			
		||||
        switch (mAddress.ReadFunction)
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            case 3:
 | 
			
		||||
                ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer03ByteBlock.Write(value);
 | 
			
		||||
                return OperResult.CreateSuccessResult();
 | 
			
		||||
            case 4:
 | 
			
		||||
                ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
 | 
			
		||||
                ModbusServer04ByteBlock.Write(value);
 | 
			
		||||
                return OperResult.CreateSuccessResult();
 | 
			
		||||
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
        }
 | 
			
		||||
        return new OperResult("功能码错误");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        ModbusAddress mAddress;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return (new OperResult(ex));
 | 
			
		||||
        }
 | 
			
		||||
        if (MulStation)
 | 
			
		||||
        {
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (Station != mAddress.Station)
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
            ModbusAddress mAddress;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (new OperResult("地址错误"));
 | 
			
		||||
                mAddress = ModbusAddress.ParseFrom(address, Station);
 | 
			
		||||
            }
 | 
			
		||||
            Init(mAddress);
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return (new OperResult(ex));
 | 
			
		||||
            }
 | 
			
		||||
            if (MulStation)
 | 
			
		||||
            {
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Station != mAddress.Station)
 | 
			
		||||
                {
 | 
			
		||||
                    return (new OperResult("地址错误"));
 | 
			
		||||
                }
 | 
			
		||||
                Init(mAddress);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
            var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
            switch (mAddress.ReadFunction)
 | 
			
		||||
            {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                    return (OperResult.CreateSuccessResult());
 | 
			
		||||
                case 2:
 | 
			
		||||
                    ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                    ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                    return (OperResult.CreateSuccessResult());
 | 
			
		||||
            }
 | 
			
		||||
            return new OperResult("功能码错误");
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
 | 
			
		||||
        var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
 | 
			
		||||
        switch (mAddress.ReadFunction)
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            case 1:
 | 
			
		||||
                ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                return (OperResult.CreateSuccessResult());
 | 
			
		||||
            case 2:
 | 
			
		||||
                ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
 | 
			
		||||
                ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
 | 
			
		||||
                return (OperResult.CreateSuccessResult());
 | 
			
		||||
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
        }
 | 
			
		||||
        return new OperResult("功能码错误");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -284,12 +317,13 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
    {
 | 
			
		||||
        return Task.FromResult(Write(address, value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void Received(SocketClient client, IRequestInfo requestInfo)
 | 
			
		||||
    protected override async Task Received(SocketClient client, ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            var requestInfo = e.RequestInfo;
 | 
			
		||||
            //接收外部报文
 | 
			
		||||
            if (requestInfo is ModbusTcpServerMessage modbusServerMessage)
 | 
			
		||||
            {
 | 
			
		||||
@@ -330,7 +364,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                        if (WriteData != null)
 | 
			
		||||
                        {
 | 
			
		||||
                            // 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
 | 
			
		||||
                            if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
 | 
			
		||||
                            if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
 | 
			
		||||
                            {
 | 
			
		||||
                                var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
@@ -367,7 +401,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                        if (WriteData != null)
 | 
			
		||||
                        {
 | 
			
		||||
 | 
			
		||||
                            if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
 | 
			
		||||
                            if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
 | 
			
		||||
                            {
 | 
			
		||||
                                var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
@@ -428,13 +462,9 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
 | 
			
		||||
    private void Init(ModbusAddress mAddress)
 | 
			
		||||
    {
 | 
			
		||||
        if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
 | 
			
		||||
            ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
 | 
			
		||||
        ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
        ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
        ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
        ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a => new ByteBlock(1024 * 128));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ public class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesTcpDataHandleAda
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>(ex.Message);
 | 
			
		||||
            return new OperResult<byte[]>(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,10 +29,10 @@ namespace ThingsGateway.Foundation.Adapter.Modbus
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override int HeadBytesLength => 6;
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CheckHeadBytes(byte[] head)
 | 
			
		||||
        public override bool CheckHeadBytes(byte[] heads)
 | 
			
		||||
        {
 | 
			
		||||
            if (head == null || head.Length != 6) return false;
 | 
			
		||||
            HeadBytes = head;
 | 
			
		||||
            if (heads == null || heads.Length != 6) return false;
 | 
			
		||||
            HeadBytes = heads;
 | 
			
		||||
 | 
			
		||||
            int num = (HeadBytes[4] * 256) + HeadBytes[5];
 | 
			
		||||
            BodyLength = num;
 | 
			
		||||
 
 | 
			
		||||
@@ -176,7 +176,7 @@ internal class OpcServer : IDisposable
 | 
			
		||||
                {
 | 
			
		||||
                    status = (OPCSERVERSTATUS)o;
 | 
			
		||||
                    serverStatus = new();
 | 
			
		||||
                    serverStatus.Version = status.wMajorVersion.ToString() + "." + status.wMinorVersion.ToString() + "." + status.wBuildNumber.ToString();
 | 
			
		||||
                    serverStatus.Version = $"{status.wMajorVersion.ToString()}.{status.wMinorVersion.ToString()}.{status.wBuildNumber.ToString()}";
 | 
			
		||||
                    serverStatus.ServerState = status.dwServerState;
 | 
			
		||||
                    serverStatus.StartTime = Comn.Convert.FileTimeToDateTime(status.ftStartTime);
 | 
			
		||||
                    serverStatus.CurrentTime = Comn.Convert.FileTimeToDateTime(status.ftCurrentTime);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,579 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<doc>
 | 
			
		||||
    <assembly>
 | 
			
		||||
        <name>ThingsGateway.Foundation.Adapter.OPCDA</name>
 | 
			
		||||
    </assembly>
 | 
			
		||||
    <members>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            移除符合条件的元素
 | 
			
		||||
            </summary>
 | 
			
		||||
            <typeparam name="T"></typeparam>
 | 
			
		||||
            <param name="this"></param>
 | 
			
		||||
            <param name="where"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_SYSTEM_DEFAULT">
 | 
			
		||||
            <summary>
 | 
			
		||||
            The WIN32 system default locale.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_USER_DEFAULT">
 | 
			
		||||
            <summary>
 | 
			
		||||
            The WIN32 user default locale.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.CreateInstance(System.Guid,System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            创建一个COM服务器的实例。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.GetSystemMessage(System.Int32)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            指定错误消息文本检索系统。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.InitializeSecurity">
 | 
			
		||||
            <summary>
 | 
			
		||||
            初始化COM安全。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            从枚举器读取guid。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            从枚举器读取guid。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.RealseComServer(System.Object)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            释放 COM 对象
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="m_server"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.Convert.FILETIME_BaseTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            windows的filetime是从1601-1-1 00:00:00开始的,datetime是从1-1-1 00:00:00开始的
 | 
			
		||||
            datetime和filetime的滴答单位都是100ns(100纳秒,千万分之一秒),所以转换时只需要考虑开始时间即可
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnDataChangedHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            值变化
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="opcItems"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnReadCompletedHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="opcItems"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnWriteCompletedHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="opcItems"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult">
 | 
			
		||||
            <summary>
 | 
			
		||||
            返回结果
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Name">
 | 
			
		||||
            <summary>
 | 
			
		||||
            ID
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Quality">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Quality
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.TimeStamp">
 | 
			
		||||
            <summary>
 | 
			
		||||
            TimeStamp
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Value">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Value
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.InitIoInterfaces(System.Object)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            建立连接
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="handle"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.ReadAsync">
 | 
			
		||||
            <summary>
 | 
			
		||||
            组读取
 | 
			
		||||
            </summary>
 | 
			
		||||
            <exception cref="T:System.Runtime.InteropServices.ExternalException"></exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OpcItem
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.#ctor(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OpcItem
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="itemId"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.AccessPath">
 | 
			
		||||
            <summary>
 | 
			
		||||
            AccessPath
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Blob">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Blob
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.BlobSize">
 | 
			
		||||
            <summary>
 | 
			
		||||
            BlobSize
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ClientHandle">
 | 
			
		||||
            <summary>
 | 
			
		||||
            ClientHandle
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.IsActive">
 | 
			
		||||
            <summary>
 | 
			
		||||
            active(1) or not(0)
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ItemID">
 | 
			
		||||
            <summary>
 | 
			
		||||
            数据项在opc server的完全名称
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Quality">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Quality
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.RunTimeDataType">
 | 
			
		||||
            <summary>
 | 
			
		||||
            RunTimeDataType
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ServerHandle">
 | 
			
		||||
            <summary>
 | 
			
		||||
            ServerHandle
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.TimeStamp">
 | 
			
		||||
            <summary>
 | 
			
		||||
            TimeStamp
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Value">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Value
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.AddGroup(System.String,System.Boolean,System.Int32,System.Single)">
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.Browse(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            获取节点
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.GetServerStatus">
 | 
			
		||||
            <summary>
 | 
			
		||||
            服务器状态
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus">
 | 
			
		||||
            <summary>
 | 
			
		||||
            ServerStatus
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.CurrentTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            CurrentTime
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.LastUpdateTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            LastUpdateTime
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.ServerState">
 | 
			
		||||
            <summary>
 | 
			
		||||
            ServerState
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.StartTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            StartTime
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.VendorInfo">
 | 
			
		||||
            <summary>
 | 
			
		||||
            VendorInfo
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.Version">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Version
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OpcDiscovery
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery.GetOpcServer(System.String,System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            GetOpcServer
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="serverName"></param>
 | 
			
		||||
            <param name="host"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPoint">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPointContainer">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnectionPoints">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnections">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumString">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumUnknown">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCCommon">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList2">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCShutdown">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CONNECTDATA">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEDIRECTION">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEFILTER">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSETYPE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCDATASOURCE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCENUMSCOPE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCEUTYPE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCNAMESPACETYPE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer10">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer20">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer30">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_XMLDAServer10">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumOPCItemAttributes">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO2">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO3">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowse">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowseServerAddressSpace">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCDataCallback">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt2">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemDeadbandMgt">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemIO">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemMgt">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemProperties">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemSamplingMgt">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCPublicGroupStateMgt">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServer">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerPublicGroups">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO2">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEELEMENT">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADER">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADERWRITE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMATTRIBUTES">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMDEF">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER1">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER2">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADERWRITE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTIES">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTY">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMRESULT">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMSTATE">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMVQT">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATUS">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Constants">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Qualities">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Properties">
 | 
			
		||||
            <exclude />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.DataChangedEventHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            订阅变化项
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="values"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCDAClient
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ItemDicts">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前保存的需订阅列表
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.#ctor(ThingsGateway.Foundation.Core.ILog)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="logger"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="E:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.DataChangedHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            数据变化事件
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.IsConnected">
 | 
			
		||||
            <summary>
 | 
			
		||||
            是否连接成功
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.OPCNode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前配置
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItems(System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.List{ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem}})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            添加节点,需要在连接成功后执行
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="items">组名称/变量节点,注意每次添加的组名称不能相同</param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItemsWithSave(System.Collections.Generic.List{System.String})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            设置节点并保存,每次重连会自动添加节点
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="items"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Connect">
 | 
			
		||||
            <summary>
 | 
			
		||||
            连接服务器
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Disconnect">
 | 
			
		||||
            <summary>
 | 
			
		||||
            断开连接
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetBrowseElements(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            浏览节点
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="itemId"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetServerStatus">
 | 
			
		||||
            <summary>
 | 
			
		||||
            获取服务状态
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Init(ThingsGateway.Foundation.Adapter.OPCDA.OPCNode)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            初始化设置
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="node"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ReadItemsWithGroup(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            按OPC组读取组内变量,结果会在订阅事件中返回
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="groupName">组名称,值为null时读取全部组</param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.RemoveItems(System.Collections.Generic.List{System.String})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            移除节点
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="items"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            批量写入值
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCDA连接配置项
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ActiveSubscribe">
 | 
			
		||||
            <summary>
 | 
			
		||||
            是否订阅
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.CheckRate">
 | 
			
		||||
            <summary>
 | 
			
		||||
            内部检测重连间隔/min
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.DeadBand">
 | 
			
		||||
            <summary>
 | 
			
		||||
            死区
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.GroupSize">
 | 
			
		||||
            <summary>
 | 
			
		||||
            分组大小
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCIP">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCIP
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCName">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCNAME
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.UpdateRate">
 | 
			
		||||
            <summary>
 | 
			
		||||
            订阅间隔
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ToString">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
    </members>
 | 
			
		||||
</doc>
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
@@ -70,6 +70,11 @@ public class OPCNode
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Description("安全策略")]
 | 
			
		||||
    public bool IsUseSecurity { get; set; } = false;
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 加载服务端数据类型
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Description("加载服务端数据类型")]
 | 
			
		||||
    public bool LoadType { get; set; } = true;
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override string ToString()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
#region copyright
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
@@ -8,11 +9,39 @@
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Opc.Ua;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.OPCUA;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// OPC UA的状态更新消息
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class OpcUaStatusEventArgs
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 日志等级,<br></br>
 | 
			
		||||
    /// 更为详细的步骤型日志输出 Trace = 0,<br></br>
 | 
			
		||||
    /// 调试信息日志Debug = 1,<br></br>
 | 
			
		||||
    /// 消息类日志输出 Info = 2,<br></br>
 | 
			
		||||
    /// 警告类日志输出 Warning = 3,<br></br>
 | 
			
		||||
    /// 错误类日志输出 Error = 4,<br></br>
 | 
			
		||||
    /// 不可控中断类日输出Critical = 5,
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public int LogLevel { get; set; }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 时间
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public DateTime Time { get; set; }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 文本
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Text { get; set; }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 读取属性过程中用于描述的
 | 
			
		||||
/// </summary>
 | 
			
		||||
@@ -22,6 +51,7 @@ public class OPCNodeAttribute
 | 
			
		||||
    /// 属性的名称
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Name { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 操作结果状态描述
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -31,10 +61,9 @@ public class OPCNodeAttribute
 | 
			
		||||
    /// 属性的类型描述
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Type { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 属性的值,如果读取错误,返回文本描述
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public object Value { get; set; }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -11,5 +11,4 @@
 | 
			
		||||
		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.56" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,468 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<doc>
 | 
			
		||||
    <assembly>
 | 
			
		||||
        <name>ThingsGateway.Foundation.Adapter.OPCUA</name>
 | 
			
		||||
    </assembly>
 | 
			
		||||
    <members>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            移除符合条件的元素
 | 
			
		||||
            </summary>
 | 
			
		||||
            <typeparam name="T"></typeparam>
 | 
			
		||||
            <param name="this"></param>
 | 
			
		||||
            <param name="where"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.SelectAsync``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Threading.Tasks.Task{``1}})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            异步Select
 | 
			
		||||
            </summary>
 | 
			
		||||
            <typeparam name="T"></typeparam>
 | 
			
		||||
            <typeparam name="TResult"></typeparam>
 | 
			
		||||
            <param name="source"></param>
 | 
			
		||||
            <param name="selector"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils">
 | 
			
		||||
            <summary>
 | 
			
		||||
            辅助类
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.Browse(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Browses the address space and returns the references found.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="session">The session.</param>
 | 
			
		||||
            <param name="nodesToBrowse">The set of browse operations to perform.</param>
 | 
			
		||||
            <param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param>
 | 
			
		||||
            <returns>
 | 
			
		||||
            The references found. Null if an error occurred.
 | 
			
		||||
            </returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.PrepareBrowseNext(Opc.Ua.BrowseResultCollection)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Create the continuation point collection from the browse result
 | 
			
		||||
            collection for the BrowseNext service.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="browseResultCollection">The browse result collection to use.</param>
 | 
			
		||||
            <returns>The collection of continuation points for the BrowseNext service.</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            浏览地址空间
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="session"></param>
 | 
			
		||||
            <param name="nodesToBrowse"></param>
 | 
			
		||||
            <param name="throwOnError"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
            <exception cref="T:Opc.Ua.ServiceResultException"></exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescription,System.Boolean,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            浏览地址空间
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="session"></param>
 | 
			
		||||
            <param name="nodeToBrowse"></param>
 | 
			
		||||
            <param name="throwOnError"></param>
 | 
			
		||||
            <param name="cancellationToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
            <exception cref="T:Opc.Ua.ServiceResultException"></exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseSuperTypesAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,System.Boolean)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            浏览地址空间并返回指定类型的所有节点
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="session"></param>
 | 
			
		||||
            <param name="typeId"></param>
 | 
			
		||||
            <param name="throwOnError"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
            <exception cref="T:Opc.Ua.ServiceResultException"></exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForInstanceAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Collects the fields for the instance.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForType(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Collects the fields for the type.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ConstructEventAsync(Opc.Ua.Client.ISession,Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList,System.Collections.Generic.Dictionary{Opc.Ua.NodeId,System.Type},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.NodeId})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Constructs an event object from a notification.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="session">The session.</param>
 | 
			
		||||
            <param name="monitoredItem">The monitored item that produced the notification.</param>
 | 
			
		||||
            <param name="notification">The notification.</param>
 | 
			
		||||
            <param name="knownEventTypes">The known event types.</param>
 | 
			
		||||
            <param name="eventTypeMappings">Mapping between event types and known event types.</param>
 | 
			
		||||
            <returns>
 | 
			
		||||
            The event object. Null if the notification is not a valid event type.
 | 
			
		||||
            </returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.DiscoverServers(Opc.Ua.ApplicationConfiguration)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Discovers the servers on the local machine.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="configuration">The configuration.</param>
 | 
			
		||||
            <returns>A list of server urls.</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.FindEventType(Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Finds the type of the event for the notification.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="monitoredItem">The monitored item.</param>
 | 
			
		||||
            <param name="notification">The notification.</param>
 | 
			
		||||
            <returns>The NodeId of the EventType.</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAttributeDisplayText(Opc.Ua.Client.ISession,System.UInt32,Opc.Ua.Variant)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            指定的属性的显示文本。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.SelectEndpoint(System.String,System.Boolean)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Finds the endpoint that best matches the current settings.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="discoveryUrl">The discovery URL.</param>
 | 
			
		||||
            <param name="useSecurity">if set to <c>true</c> select an endpoint that uses security.</param>
 | 
			
		||||
            <returns>The best available endpoint.</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.TranslateBrowsePaths(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.NamespaceTable,System.Threading.CancellationToken,System.String[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            返回一组相对路径的节点id
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Collects the fields for the instance node.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="session">The session.</param>
 | 
			
		||||
            <param name="nodeId">The node id.</param>
 | 
			
		||||
            <param name="parentPath">The parent path.</param>
 | 
			
		||||
            <param name="fields">The event fields.</param>
 | 
			
		||||
            <param name="fieldNodeIds">The node id for the declaration of the field.</param>
 | 
			
		||||
            <param name="foundNodes">The table of found nodes.</param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ContainsPath(Opc.Ua.SimpleAttributeOperandCollection,Opc.Ua.QualifiedNameCollection)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            判断指定的select子句包含的浏览路径。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAccessLevelDisplayText(System.Byte)">
 | 
			
		||||
             <summary>
 | 
			
		||||
            访问级别属性的显示文本。
 | 
			
		||||
             </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetEventNotifierDisplayText(System.Byte)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            事件通知属性的显示文本
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils">
 | 
			
		||||
            <summary>
 | 
			
		||||
            扩展方法
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Decode(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析获取DataValue
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecoderObject(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析获取object
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecodeRawData(Opc.Ua.JsonDecoder,Opc.Ua.BuiltInType,System.Int32,System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DecodeRawData
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Encode(Opc.Ua.IServiceMessageContext,Opc.Ua.BuiltInType,System.Object)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCUAValue解析为Jtoken
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="Context"></param>
 | 
			
		||||
            <param name="type"></param>
 | 
			
		||||
            <param name="value"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CreateEncoder(Opc.Ua.IServiceMessageContext,System.IO.Stream,System.Boolean,System.Boolean,System.Boolean,System.Boolean)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            CreateEncoder
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CalculateActualValueRank(Newtonsoft.Json.Linq.JToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            维度
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="jToken"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCUAClient配置项
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.OPCUrl">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCUrl
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UserName">
 | 
			
		||||
            <summary>
 | 
			
		||||
            登录账号
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.Password">
 | 
			
		||||
            <summary>
 | 
			
		||||
            登录密码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.CheckDomain">
 | 
			
		||||
            <summary>
 | 
			
		||||
            检查域
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UpdateRate">
 | 
			
		||||
            <summary>
 | 
			
		||||
            更新间隔
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ActiveSubscribe">
 | 
			
		||||
            <summary>
 | 
			
		||||
            是否订阅
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.GroupSize">
 | 
			
		||||
            <summary>
 | 
			
		||||
            分组大小
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.DeadBand">
 | 
			
		||||
            <summary>
 | 
			
		||||
            死区
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.KeepAliveInterval">
 | 
			
		||||
            <summary>
 | 
			
		||||
            KeepAliveInterval/ms
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.IsUseSecurity">
 | 
			
		||||
            <summary>
 | 
			
		||||
            安全策略
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ToString">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCUA.DataChangedEventHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            订阅委托
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="value"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCUAClient
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCNode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前配置
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ProductUri">
 | 
			
		||||
            <summary>
 | 
			
		||||
            ProductUri
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Variables">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前保存的变量名称列表
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient._variableDicts">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前的变量名称/OPC变量节点
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.dic_subscriptions">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前的订阅组,组名称/组
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReConnectHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            SessionReconnectHandler
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.#ctor(ThingsGateway.Foundation.Core.ILog)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            默认的构造函数,实例化一个新的OPC UA类
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="E:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.DataChangedHandler">
 | 
			
		||||
            <summary>
 | 
			
		||||
            订阅
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AppConfig">
 | 
			
		||||
            <summary>
 | 
			
		||||
            配置信息
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Connected">
 | 
			
		||||
            <summary>
 | 
			
		||||
            连接状态
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCUAName">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OPCUAClient
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Session">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前活动会话。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AddSubscriptionAsync(System.String,System.String[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            新增订阅,需要指定订阅组名称,订阅的tag名数组
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveAllSubscription">
 | 
			
		||||
            <summary>
 | 
			
		||||
            移除所有的订阅消息
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveSubscription(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            移除订阅消息
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="subscriptionName">组名称</param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.BrowseNodeReferenceAsync(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            浏览一个节点的引用
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="tag">节点值</param>
 | 
			
		||||
            <returns>引用节点描述</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.CallMethodByNodeId(System.String,System.String,System.Object[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            调用服务器的方法
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="tagParent">方法的父节点tag</param>
 | 
			
		||||
            <param name="tag">方法的节点tag</param>
 | 
			
		||||
            <param name="args">传递的参数</param>
 | 
			
		||||
            <returns>输出的结果值</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadHistoryRawDataValues(System.String,System.DateTime,System.DateTime,System.UInt32,System.Boolean,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取历史数据
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="tag">节点的索引</param>
 | 
			
		||||
            <param name="start">开始时间</param>
 | 
			
		||||
            <param name="end">结束时间</param>
 | 
			
		||||
            <param name="count">读取的个数</param>
 | 
			
		||||
            <param name="containBound">是否包含边界</param>
 | 
			
		||||
            <param name="cancellationToken">cancellationToken</param>
 | 
			
		||||
            <returns>读取的数据列表</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync">
 | 
			
		||||
            <summary>
 | 
			
		||||
            连接到服务器
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Disconnect">
 | 
			
		||||
            <summary>
 | 
			
		||||
            断开连接。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Creates a new session.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns>The new session object.</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(System.String[],System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            从服务器读取值
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            异步写opc标签
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(Opc.Ua.NodeId[],System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            从服务器读取值
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNodeAsync(System.String,System.Boolean,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            从服务器或缓存读取节点
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取一个节点的所有属性
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.Collections.Generic.List{System.String},System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取节点的所有属性
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributes(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取一个节点的所有属性
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="tag">节点信息</param>
 | 
			
		||||
            <returns>节点的特性值</returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Dispose(System.Boolean)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Server_ReconnectComplete(System.Object,System.EventArgs)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            连接处理器连接事件处理完成。
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取属性过程中用于描述的
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Name">
 | 
			
		||||
            <summary>
 | 
			
		||||
            属性的名称
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.StatusCode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            操作结果状态描述
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Type">
 | 
			
		||||
            <summary>
 | 
			
		||||
            属性的类型描述
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Value">
 | 
			
		||||
            <summary>
 | 
			
		||||
            属性的值,如果读取错误,返回文本描述
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
    </members>
 | 
			
		||||
</doc>
 | 
			
		||||
@@ -250,44 +250,44 @@ public class SiemensAddress : DeviceAddressBase
 | 
			
		||||
    {
 | 
			
		||||
        if (DataCode == (byte)S7Area.TM)
 | 
			
		||||
        {
 | 
			
		||||
            return "T" + Address.ToString() + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"T{Address.ToString()}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
        if (DataCode == (byte)S7Area.CT)
 | 
			
		||||
        {
 | 
			
		||||
            return "C" + Address.ToString() + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"C{Address.ToString()}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (DataCode == (byte)S7Area.AI)
 | 
			
		||||
        {
 | 
			
		||||
            return "AI" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"AI{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (DataCode == (byte)S7Area.AQ)
 | 
			
		||||
        {
 | 
			
		||||
            return "AQ" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"AQ{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (DataCode == (byte)S7Area.PE)
 | 
			
		||||
        {
 | 
			
		||||
            return "I" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"I{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (DataCode == (byte)S7Area.PA)
 | 
			
		||||
        {
 | 
			
		||||
            return "Q" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"Q{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (DataCode == (byte)S7Area.MK)
 | 
			
		||||
        {
 | 
			
		||||
            return "M" + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
            return $"M{GetStringAddress(AddressStart)}{(IsWString ? ";W=true;" : ";W=false;")}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return DataCode == (byte)S7Area.DB ? "DB" + DbBlock.ToString() + "." + GetStringAddress(AddressStart) + (IsWString ? ";W=true;" : ";W=false;") : Address.ToString() + (IsWString ? ";W=true;" : ";W=false;");
 | 
			
		||||
        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)
 | 
			
		||||
    {
 | 
			
		||||
        return addressStart % 8 == 0 ? (addressStart / 8).ToString() : string.Format("{0}.{1}", addressStart / 8, addressStart % 8);
 | 
			
		||||
        return addressStart % 8 == 0 ? (addressStart / 8).ToString() : $"{addressStart / 8}.{addressStart % 8}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.Siemens;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.Siemens;
 | 
			
		||||
 | 
			
		||||
internal static class PackHelper
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,6 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            tcpClient.Connected += Connected;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -293,8 +292,8 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override void SetDataAdapter(object socketClient = null)
 | 
			
		||||
        {
 | 
			
		||||
            SiemensS7PLCDataHandleAdapter DataHandleAdapter = new();
 | 
			
		||||
            TcpClient.SetDataHandlingAdapter(DataHandleAdapter);
 | 
			
		||||
            SiemensS7PLCDataHandleAdapter dataHandleAdapter = new();
 | 
			
		||||
            TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -476,17 +475,20 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        private void Connected(ITcpClient client, ConnectedEventArgs e)
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task Connected(ITcpClient client, ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var result1 = SendThenResponse(ISO_CR);
 | 
			
		||||
                NormalDataHandlingAdapter dataHandleAdapter = new();
 | 
			
		||||
                TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
 | 
			
		||||
                var result1 = await SendThenResponseAsync(ISO_CR);
 | 
			
		||||
                if (!result1.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger?.Warning($"{client.IP} : {client.Port}:ISO_TP握手失败-{result1.Message}");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var result2 = SendThenResponse(S7_PN);
 | 
			
		||||
                var result2 = await SendThenResponseAsync(S7_PN);
 | 
			
		||||
                if (!result2.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger?.Warning($"{client.IP} : {client.Port}:PDU初始化失败-{result2.Message}");
 | 
			
		||||
@@ -499,7 +501,11 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Exception(ex);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                SetDataAdapter();
 | 
			
		||||
            }
 | 
			
		||||
            await base.Connected(client, e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,336 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<doc>
 | 
			
		||||
    <assembly>
 | 
			
		||||
        <name>ThingsGateway.Foundation.Adapter.Siemens</name>
 | 
			
		||||
    </assembly>
 | 
			
		||||
    <members>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.S7Area">
 | 
			
		||||
            <summary>
 | 
			
		||||
            区域
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.PE">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.PA">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.MK">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.DB">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.CT">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.TM">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.AI">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.AQ">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress">
 | 
			
		||||
            <summary>
 | 
			
		||||
            西门子PLC地址数据信息
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.BitCode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            bit位偏移
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.DataCode">
 | 
			
		||||
            <summary>
 | 
			
		||||
            数据块代码
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.DbBlock">
 | 
			
		||||
            <summary>
 | 
			
		||||
            DB块数据信息
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.GetAddressStart(System.String,System.Boolean)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            获取起始地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="address"></param>
 | 
			
		||||
            <param name="isCounterOrTimer"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.GetBitCode(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            获取bit
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="address"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ParseFrom(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="address"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ParseFrom(System.String,System.Int32)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            解析地址
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="address"></param>
 | 
			
		||||
            <param name="length"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.Parse(System.String,System.Int32)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ToString">
 | 
			
		||||
            <inheritdoc />
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.DateTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            https://github.com/S7NetPlus/s7netplus/blob/develop/S7.Net/Types/DateTime.cs
 | 
			
		||||
            Contains the methods to convert between <see cref="T:System.DateTime"/> and S7 representation of datetime values.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.DateTime.SpecMaximumDateTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            The maximum <see cref="T:System.DateTime"/> value supported by the specification.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.DateTime.SpecMinimumDateTime">
 | 
			
		||||
            <summary>
 | 
			
		||||
            The minimum <see cref="T:System.DateTime"/> value supported by the specification.
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.FromByteArray(System.Byte[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Parses a <see cref="T:System.DateTime"/> value from bytes.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="bytes">Input bytes read from PLC.</param>
 | 
			
		||||
            <returns>A <see cref="T:System.DateTime"/> object representing the value read from PLC.</returns>
 | 
			
		||||
            <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the length of
 | 
			
		||||
              <paramref name="bytes"/> is not 8 or any value in <paramref name="bytes"/>
 | 
			
		||||
              is outside the valid range of values.</exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToArray(System.Byte[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Parses an array of <see cref="T:System.DateTime"/> values from bytes.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="bytes">Input bytes read from PLC.</param>
 | 
			
		||||
            <returns>An array of <see cref="T:System.DateTime"/> objects representing the values read from PLC.</returns>
 | 
			
		||||
            <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the length of
 | 
			
		||||
              <paramref name="bytes"/> is not a multiple of 8 or any value in
 | 
			
		||||
              <paramref name="bytes"/> is outside the valid range of values.</exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToByteArray(System.DateTime)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Converts a <see cref="T:System.DateTime"/> value to a byte array.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="dateTime">The DateTime value to convert.</param>
 | 
			
		||||
            <returns>A byte array containing the S7 date time representation of <paramref name="dateTime"/>.</returns>
 | 
			
		||||
            <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the value of
 | 
			
		||||
              <paramref name="dateTime"/> is before <see cref="P:SpecMinimumDateTime"/>
 | 
			
		||||
              or after <see cref="P:SpecMaximumDateTime"/>.</exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToByteArray(System.DateTime[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Converts an array of <see cref="T:System.DateTime"/> values to a byte array.
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="dateTimes">The DateTime values to convert.</param>
 | 
			
		||||
            <returns>A byte array containing the S7 date time representations of <paramref name="dateTimes"/>.</returns>
 | 
			
		||||
            <exception cref="T:System.ArgumentOutOfRangeException">Thrown when any value of
 | 
			
		||||
              <paramref name="dateTimes"/> is before <see cref="P:SpecMinimumDateTime"/>
 | 
			
		||||
              or after <see cref="P:SpecMaximumDateTime"/>.</exception>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensHelper.S7_MULRW_HEADER">
 | 
			
		||||
            <summary>
 | 
			
		||||
            S7连读写请求头(包含ISO头和COTP头) 
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Bit">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Byte">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Char">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Word">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Int">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.DWord">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.DInt">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Real">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Counter">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Timer">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage.HeadBytesLength">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage.CheckHeadBytes(System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S200">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S200Smart">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S300">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S400">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S1200">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S1500">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC">
 | 
			
		||||
            <summary>
 | 
			
		||||
            相关命令含义源自网络资料/Shrap7/s7netplus
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <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>
 | 
			
		||||
            <param name="tcpClient"></param>
 | 
			
		||||
            <param name="siemensPLCEnum"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.CurrentPlc">
 | 
			
		||||
            <summary>
 | 
			
		||||
            当前PLC类型
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.GetAddressDescription">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.GetBitOffset(System.String)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="address"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.DestTSAP">
 | 
			
		||||
            <summary>
 | 
			
		||||
            远程TSAP,需重新连接
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.LocalTSAP">
 | 
			
		||||
            <summary>
 | 
			
		||||
            本地TSAP,需重新连接
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.PDULength">
 | 
			
		||||
            <summary>
 | 
			
		||||
            PDULength
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.Rack">
 | 
			
		||||
            <summary>
 | 
			
		||||
            机架号,需重新连接
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.Slot">
 | 
			
		||||
            <summary>
 | 
			
		||||
            槽号,需重新连接
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateAsync(System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取日期
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateTimeAsync(System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取时间
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadStringAsync(System.String,System.Text.Encoding,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            读取变长字符串
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.SetDataAdapter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入日期
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateTimeAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            写入时间
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter">
 | 
			
		||||
            <summary>
 | 
			
		||||
            SiemensS7PLCDataHandleAdapter
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.PackCommand(System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.GetInstance">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage,System.Byte[],System.Byte[],System.Byte[])">
 | 
			
		||||
            <inheritdoc/>
 | 
			
		||||
        </member>
 | 
			
		||||
    </members>
 | 
			
		||||
</doc>
 | 
			
		||||
@@ -24,7 +24,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    public ReadWriteDevicesSerialSessionBase(SerialSession serialSession)
 | 
			
		||||
    {
 | 
			
		||||
        SerialSession = serialSession;
 | 
			
		||||
        WaitingClientEx = SerialSession.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
        WaitingClientEx = SerialSession.CreateWaitingClient(new() { });
 | 
			
		||||
        SerialSession.Received -= Received;
 | 
			
		||||
        SerialSession.Connecting -= Connecting;
 | 
			
		||||
        SerialSession.Connected -= Connected;
 | 
			
		||||
@@ -40,21 +40,15 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收解析
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected virtual void Received(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    protected virtual Task Received(SerialSession client, ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    private void Received(SerialSession client, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            Received(byteBlock, requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            Logger.Exception(this, ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 串口管理对象
 | 
			
		||||
@@ -102,8 +96,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { BreakTrigger = true, ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = SerialSession.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { };
 | 
			
		||||
            ResponsedData result = SerialSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -117,8 +111,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = await SerialSession.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { };
 | 
			
		||||
            ResponsedData result = await SerialSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -132,24 +126,34 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        return SerialSession.SerialProperty.ToString();
 | 
			
		||||
    }
 | 
			
		||||
    private void Connected(ISerialSession client, ConnectedEventArgs e)
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Connected
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    protected virtual Task Connected(ISerialSession client, ConnectedEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.SerialProperty.ToString() + "连接成功");
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Connecting(ISerialSession client, SerialConnectingEventArgs e)
 | 
			
		||||
    private Task Connecting(ISerialSession client, SerialConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.SerialProperty.ToString() + "正在连接");
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Disconnected(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    private Task Disconnected(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.SerialProperty.ToString() + "断开连接-" + e.Message);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Disconnecting(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    private Task Disconnecting(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.SerialProperty.ToString() + "正在主动断开连接-" + e.Message);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,7 +23,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    public ReadWriteDevicesTcpClientBase(TcpClient tcpClient)
 | 
			
		||||
    {
 | 
			
		||||
        TcpClient = tcpClient;
 | 
			
		||||
        WaitingClientEx = TcpClient.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
        WaitingClientEx = TcpClient.CreateWaitingClient(new() { });
 | 
			
		||||
        TcpClient.Connecting -= Connecting;
 | 
			
		||||
        TcpClient.Connected -= Connected;
 | 
			
		||||
        TcpClient.Disconnecting -= Disconnecting;
 | 
			
		||||
@@ -59,7 +59,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override Task ConnectAsync(CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return TcpClient.ConnectAsync(ConnectTimeOut);
 | 
			
		||||
        return TcpClient.ConnectAsync(ConnectTimeOut, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -86,8 +86,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { BreakTrigger = true, ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = TcpClient.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { };
 | 
			
		||||
            ResponsedData result = TcpClient.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -101,8 +101,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = await TcpClient.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { };
 | 
			
		||||
            ResponsedData result = await TcpClient.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -116,24 +116,34 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        return TcpClient.RemoteIPHost.ToString();
 | 
			
		||||
    }
 | 
			
		||||
    private void Connected(ITcpClient client, ConnectedEventArgs e)
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Connected
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    protected virtual Task Connected(ITcpClient client, ConnectedEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.RemoteIPHost.ToString() + "连接成功");
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Connecting(ITcpClient client, ConnectingEventArgs e)
 | 
			
		||||
    private Task Connecting(ITcpClient client, ConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.RemoteIPHost.ToString() + "正在连接");
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Disconnected(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    private Task Disconnected(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message);
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}断开连接-{e.Message}");
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    private Task Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message);
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}正在主动断开连接-{e.Message}");
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -77,57 +77,54 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
 | 
			
		||||
        if (CascadeDisposal)
 | 
			
		||||
            TcpService.SafeDispose();
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收解析
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    protected virtual Task Received(SocketClient client, ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override string ToString()
 | 
			
		||||
    {
 | 
			
		||||
        return TcpService.ServerName;
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收解析
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected virtual void Received(SocketClient client, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    protected virtual void Connected(SocketClient client, ConnectedEventArgs e)
 | 
			
		||||
    protected virtual Task Connected(SocketClient client, ConnectedEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "连接成功");
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}连接成功");
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected virtual void Connecting(SocketClient client, ConnectingEventArgs e)
 | 
			
		||||
    protected virtual Task Connecting(SocketClient client, ConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}正在连接");
 | 
			
		||||
        SetDataAdapter(client);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected virtual void Disconnected(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    protected virtual Task Disconnected(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message);
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}断开连接-{e.Message}");
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected virtual void Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    protected virtual Task Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message);
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}正在主动断开连接-{e.Message}");
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Received(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            Received(client, requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            Logger.Exception(this, ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,7 +22,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        UdpSession = udpSession;
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        WaitingClientEx = UdpSession.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
        WaitingClientEx = UdpSession.CreateWaitingClient(new() {  });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -64,8 +64,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = UdpSession.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions {  };
 | 
			
		||||
            ResponsedData result = UdpSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -79,8 +79,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = await UdpSession.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions {  };
 | 
			
		||||
            ResponsedData result = await UdpSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,12 @@ public sealed class EasyLock
 | 
			
		||||
    private static long lockWaitCount;
 | 
			
		||||
    private readonly SemaphoreSlim m_waiterLock = new SemaphoreSlim(1);
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public EasyLock(bool initialState = true)
 | 
			
		||||
    {
 | 
			
		||||
        if (!initialState)
 | 
			
		||||
            m_waiterLock.Wait();
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    ~EasyLock()
 | 
			
		||||
    {
 | 
			
		||||
        m_waiterLock.SafeDispose();
 | 
			
		||||
@@ -45,39 +51,41 @@ public sealed class EasyLock
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 进入锁
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void Wait()
 | 
			
		||||
    public void Wait(CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        Interlocked.Increment(ref lockWaitCount);
 | 
			
		||||
        m_waiterLock.Wait();
 | 
			
		||||
        m_waiterLock.Wait(cancellationToken);
 | 
			
		||||
        Interlocked.Decrement(ref lockWaitCount);
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 进入锁
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void Wait(TimeSpan timeSpan, CancellationToken cancellationToken)
 | 
			
		||||
    public bool Wait(TimeSpan timeSpan, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        Interlocked.Increment(ref lockWaitCount);
 | 
			
		||||
        m_waiterLock.Wait(timeSpan, cancellationToken);
 | 
			
		||||
        var data = m_waiterLock.Wait(timeSpan, cancellationToken);
 | 
			
		||||
        Interlocked.Decrement(ref lockWaitCount);
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 进入锁
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public async Task WaitAsync()
 | 
			
		||||
    public async Task WaitAsync(CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        Interlocked.Increment(ref lockWaitCount);
 | 
			
		||||
        await m_waiterLock.WaitAsync();
 | 
			
		||||
        await m_waiterLock.WaitAsync(cancellationToken);
 | 
			
		||||
        Interlocked.Decrement(ref lockWaitCount);
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 进入锁
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public async Task WaitAsync(TimeSpan timeSpan, CancellationToken cancellationToken)
 | 
			
		||||
    public async Task<bool> WaitAsync(TimeSpan timeSpan, CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        Interlocked.Increment(ref lockWaitCount);
 | 
			
		||||
        await m_waiterLock.WaitAsync(timeSpan, cancellationToken);
 | 
			
		||||
        var data = await m_waiterLock.WaitAsync(timeSpan, cancellationToken);
 | 
			
		||||
        Interlocked.Decrement(ref lockWaitCount);
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -143,6 +143,21 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
 | 
			
		||||
        GoSend(bytes, 0, bytes.Length);
 | 
			
		||||
        Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}");
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 发送方法,会重新建立<see cref="Request"/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected async Task GoSendAsync(byte[] item)
 | 
			
		||||
    {
 | 
			
		||||
        byte[] bytes;
 | 
			
		||||
        if (IsSendPackCommand)
 | 
			
		||||
            bytes = PackCommand(item);
 | 
			
		||||
        else
 | 
			
		||||
            bytes = item;
 | 
			
		||||
        Request = GetInstance();
 | 
			
		||||
        Request.SendBytes = bytes;
 | 
			
		||||
        await GoSendAsync(bytes, 0, bytes.Length);
 | 
			
		||||
        Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void PreviewSend(byte[] buffer, int offset, int length)
 | 
			
		||||
@@ -150,6 +165,12 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
 | 
			
		||||
        GoSend(buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
    {
 | 
			
		||||
        return GoSendAsync(buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 报文拆包
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -128,11 +128,6 @@ public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHa
 | 
			
		||||
    {
 | 
			
		||||
        throw new System.NotImplementedException();//因为设置了不支持拼接发送,所以该方法可以不实现。
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void PreviewSend(IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        throw new System.NotImplementedException();//因为设置了不支持,所以该方法可以不实现。
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void Reset()
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ public abstract class MessageBase : OperResult<byte[]>, IMessage
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public abstract bool CheckHeadBytes(byte[] head);
 | 
			
		||||
    public abstract bool CheckHeadBytes(byte[] heads);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 写入<see cref="SendBytes"/>后触发此方法
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ public interface IMessage : IOperResult, IRequestInfo
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 检查头子节的合法性,并赋值<see cref="BodyLength"/><br />
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="head">接收的头子节</param>
 | 
			
		||||
    /// <param name="heads">接收的头子节</param>
 | 
			
		||||
    /// <returns>是否成功的结果</returns>
 | 
			
		||||
    bool CheckHeadBytes(byte[] head);
 | 
			
		||||
    bool CheckHeadBytes(byte[] heads);
 | 
			
		||||
}
 | 
			
		||||
@@ -28,7 +28,7 @@ public class ByteTransformUtil
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<TResult>(string.Format("{0} {1} : Length({2}) {3}", "转换失败", result.Content.ToHexString(), result.Content.Length, ex.Message));
 | 
			
		||||
            return new OperResult<TResult>(string.Format("{0} {1} : Length({2}) {3}", "转换失败", result.Content.ToHexString(), result.Content.Length, ex));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ public static class JTokenUtil
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception)
 | 
			
		||||
        {
 | 
			
		||||
            tagValue = JToken.Parse("\"" + item + "\"");
 | 
			
		||||
            tagValue = JToken.Parse($"\"{item}\"");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return tagValue;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,5 +19,20 @@
 | 
			
		||||
		<PackageReference Include="System.IO.Ports" Version="7.0.0" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\favicon-16x16.png" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\favicon-32x32.png" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\index.html" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\oauth2-redirect.html" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\openapi.json" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-bundle.js" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-es-bundle-core.js" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-es-bundle.js" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-standalone-preset.js" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui.css" />
 | 
			
		||||
		<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui.js" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,10 +27,9 @@ using System.Runtime.CompilerServices;
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 具有释放的对象。
 | 
			
		||||
    /// 并未实现析构函数相关。
 | 
			
		||||
    /// 具有释放的对象。内部实现了GC.SuppressFinalize,但不包括析构函数相关。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class DisposableObject : IDisposable
 | 
			
		||||
    public partial class DisposableObject : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 判断是否已释放。
 | 
			
		||||
@@ -65,11 +64,12 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 释放资源。
 | 
			
		||||
        /// 释放资源。内部已经处理了<see cref="GC.SuppressFinalize(object)"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            this.Dispose(disposing: true);
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        this.OnError(ex.Message, false, true);
 | 
			
		||||
                        this.OnError(ex.ToString(), false, true);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return FilterResult.GoOn;
 | 
			
		||||
@@ -121,7 +121,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            this.OnError(ex.Message, false, true);
 | 
			
		||||
                            this.OnError(ex.ToString(), false, true);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    return FilterResult.GoOn;
 | 
			
		||||
 
 | 
			
		||||
@@ -69,14 +69,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.Owner = owner;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        public void SendInput(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            this.PreviewSend(requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在解析时发生错误。
 | 
			
		||||
@@ -96,11 +88,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected abstract void PreviewSend(IRequestInfo requestInfo);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重置解析器到初始状态,一般在<see cref="OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。
 | 
			
		||||
 
 | 
			
		||||
@@ -78,6 +78,24 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            throw new System.NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override Task PreviewSendAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return this.GoSendAsync(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -242,6 +242,131 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override Task PreviewSendAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            if (length < this.MinPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送数据小于设定值,相同解析器可能无法收到有效数据,已终止发送");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ByteBlock byteBlock = null;
 | 
			
		||||
            byte[] lenBytes = null;
 | 
			
		||||
 | 
			
		||||
            switch (this.FixedHeaderType)
 | 
			
		||||
            {
 | 
			
		||||
                case FixedHeaderType.Byte:
 | 
			
		||||
                    {
 | 
			
		||||
                        var dataLen = (byte)(length - offset);
 | 
			
		||||
                        byteBlock = new ByteBlock(dataLen + 1);
 | 
			
		||||
                        lenBytes = new byte[] { dataLen };
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                case FixedHeaderType.Ushort:
 | 
			
		||||
                    {
 | 
			
		||||
                        var dataLen = (ushort)(length - offset);
 | 
			
		||||
                        byteBlock = new ByteBlock(dataLen + 2);
 | 
			
		||||
                        lenBytes = TouchSocketBitConverter.Default.GetBytes(dataLen);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                case FixedHeaderType.Int:
 | 
			
		||||
                    {
 | 
			
		||||
                        var dataLen = length - offset;
 | 
			
		||||
                        byteBlock = new ByteBlock(dataLen + 4);
 | 
			
		||||
                        lenBytes = TouchSocketBitConverter.Default.GetBytes(dataLen);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Write(lenBytes);
 | 
			
		||||
                byteBlock.Write(buffer, offset, length);
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            if (transferBytes.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var length = 0;
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            {
 | 
			
		||||
                length += item.Count;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length < this.MinPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送数据小于设定值,相同解析器可能无法收到有效数据,已终止发送");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ByteBlock byteBlock = null;
 | 
			
		||||
            byte[] lenBytes = null;
 | 
			
		||||
 | 
			
		||||
            switch (this.FixedHeaderType)
 | 
			
		||||
            {
 | 
			
		||||
                case FixedHeaderType.Byte:
 | 
			
		||||
                    {
 | 
			
		||||
                        var dataLen = (byte)length;
 | 
			
		||||
                        byteBlock = new ByteBlock(dataLen + 1);
 | 
			
		||||
                        lenBytes = new byte[] { dataLen };
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                case FixedHeaderType.Ushort:
 | 
			
		||||
                    {
 | 
			
		||||
                        var dataLen = (ushort)length;
 | 
			
		||||
                        byteBlock = new ByteBlock(dataLen + 2);
 | 
			
		||||
                        lenBytes = TouchSocketBitConverter.Default.GetBytes(dataLen);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                case FixedHeaderType.Int:
 | 
			
		||||
                    {
 | 
			
		||||
                        byteBlock = new ByteBlock(length + 4);
 | 
			
		||||
                        lenBytes = TouchSocketBitConverter.Default.GetBytes(length);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Write(lenBytes);
 | 
			
		||||
                foreach (var item in transferBytes)
 | 
			
		||||
                {
 | 
			
		||||
                    byteBlock.Write(item.Array, item.Offset, item.Count);
 | 
			
		||||
                }
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -183,6 +183,70 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override Task PreviewSendAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            var dataLen = length - offset;
 | 
			
		||||
            if (dataLen > this.FixedSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new OverlengthException("发送的数据包长度大于FixedSize");
 | 
			
		||||
            }
 | 
			
		||||
            var byteBlock = new ByteBlock(this.FixedSize);
 | 
			
		||||
 | 
			
		||||
            byteBlock.Write(buffer, offset, length);
 | 
			
		||||
            for (var i = byteBlock.Pos; i < this.FixedSize; i++)
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Buffer[i] = 0;
 | 
			
		||||
            }
 | 
			
		||||
            byteBlock.SetLength(this.FixedSize);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            var length = 0;
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            {
 | 
			
		||||
                length += item.Count;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length > this.FixedSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new OverlengthException("发送的数据包长度大于FixedSize");
 | 
			
		||||
            }
 | 
			
		||||
            var byteBlock = new ByteBlock(this.FixedSize);
 | 
			
		||||
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Write(item.Array, item.Offset, item.Count);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Array.Clear(byteBlock.Buffer, byteBlock.Pos, this.FixedSize);
 | 
			
		||||
            byteBlock.SetLength(this.FixedSize);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -240,5 +240,64 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override Task PreviewSendAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送的数据长度大于适配器设定的最大值,接收方可能会抛弃。");
 | 
			
		||||
            }
 | 
			
		||||
            var dataLen = length - offset + this.m_terminatorCode.Length;
 | 
			
		||||
            var byteBlock = new ByteBlock(dataLen);
 | 
			
		||||
            byteBlock.Write(buffer, offset, length);
 | 
			
		||||
            byteBlock.Write(this.m_terminatorCode);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            var length = 0;
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            {
 | 
			
		||||
                length += item.Count;
 | 
			
		||||
            }
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送的数据长度大于适配器设定的最大值,接收方可能会抛弃。");
 | 
			
		||||
            }
 | 
			
		||||
            var dataLen = length + this.m_terminatorCode.Length;
 | 
			
		||||
            var byteBlock = new ByteBlock(dataLen);
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Write(item.Array, item.Offset, item.Count);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            byteBlock.Write(this.m_terminatorCode);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                byteBlock.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,19 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
 | 
			
		||||
//  CSDN博客:https://blog.csdn.net/qq_40374647
 | 
			
		||||
//  哔哩哔哩视频:https://space.bilibili.com/94253567
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/RRQM_Home
 | 
			
		||||
//  Github源代码仓库:https://github.com/RRQM
 | 
			
		||||
//  API首页:http://rrqm_home.gitee.io/touchsocket/
 | 
			
		||||
//  交流QQ群:234762506
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -37,4 +50,4 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool? UpdateCacheTimeWhenRev { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -36,9 +36,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        public TimeSpan CacheTimeout { get; set; } = TimeSpan.FromSeconds(1);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否启用缓存超时。默认true。
 | 
			
		||||
        /// 是否启用缓存超时。默认false。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool CacheTimeoutEnable { get; set; } = true;
 | 
			
		||||
        public bool CacheTimeoutEnable { get; set; } = false;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当接收数据处理完成后,回调该函数执行接收
 | 
			
		||||
@@ -46,10 +46,15 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        public Action<ByteBlock, IRequestInfo> ReceivedCallBack { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当接收数据处理完成后,回调该函数执行发送
 | 
			
		||||
        /// 当发送数据处理完成后,回调该函数执行发送
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<byte[], int, int> SendCallBack { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据处理完成后,回调该函数执行异步发送
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<byte[], int, int, Task> SendAsyncCallBack { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否在收到数据时,即刷新缓存时间。默认true。
 | 
			
		||||
        /// <list type="number">
 | 
			
		||||
@@ -64,6 +69,12 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected DateTime LastCacheTime { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CanSendRequestInfo => false;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CanSplicingSend => false;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 收到数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -76,10 +87,21 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                this.OnError(ex.Message);
 | 
			
		||||
                this.OnError(ex.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region SendInput
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        public void SendInput(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            this.PreviewSend(requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -100,6 +122,98 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.PreviewSend(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public Task SendInputAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            return this.PreviewSendAsync(requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer"></param>
 | 
			
		||||
        /// <param name="offset"></param>
 | 
			
		||||
        /// <param name="length"></param>
 | 
			
		||||
        public Task SendInputAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return this.PreviewSendAsync(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="transferBytes"></param>
 | 
			
		||||
        public Task SendInputAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return this.PreviewSendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected virtual void PreviewSend(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">数据</param>
 | 
			
		||||
        /// <param name="offset">偏移</param>
 | 
			
		||||
        /// <param name="length">长度</param>
 | 
			
		||||
        protected virtual void PreviewSend(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            this.GoSend(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 组合发送预处理数据,
 | 
			
		||||
        /// 当属性SplicingSend实现为True时,系统才会调用该方法。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="transferBytes">代发送数据组合</param>
 | 
			
		||||
        protected virtual void PreviewSend(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected virtual Task PreviewSendAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">数据</param>
 | 
			
		||||
        /// <param name="offset">偏移</param>
 | 
			
		||||
        /// <param name="length">长度</param>
 | 
			
		||||
        protected virtual Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return this.GoSendAsync(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 组合发送预处理数据,
 | 
			
		||||
        /// 当属性SplicingSend实现为True时,系统才会调用该方法。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="transferBytes">代发送数据组合</param>
 | 
			
		||||
        protected virtual Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion SendInput
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -130,27 +244,24 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.SendCallBack.Invoke(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步发送已经经过预先处理后的数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer"></param>
 | 
			
		||||
        /// <param name="offset"></param>
 | 
			
		||||
        /// <param name="length"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected Task GoSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendAsyncCallBack.Invoke(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当接收到数据后预先处理数据,然后调用<see cref="GoReceived(ByteBlock, IRequestInfo)"/>处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        protected abstract void PreviewReceived(ByteBlock byteBlock);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">数据</param>
 | 
			
		||||
        /// <param name="offset">偏移</param>
 | 
			
		||||
        /// <param name="length">长度</param>
 | 
			
		||||
        protected abstract void PreviewSend(byte[] buffer, int offset, int length);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 组合发送预处理数据,
 | 
			
		||||
        /// 当属性SplicingSend实现为True时,系统才会调用该方法。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="transferBytes">代发送数据组合</param>
 | 
			
		||||
        protected abstract void PreviewSend(IList<ArraySegment<byte>> transferBytes);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重置解析器到初始状态,一般在<see cref="DataHandlingAdapter.OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -63,9 +63,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static SingleStreamDataAdapterTester CreateTester(SingleStreamDataHandlingAdapter adapter, int bufferLength = 1024, Action<ByteBlock, IRequestInfo> receivedCallBack = default)
 | 
			
		||||
        {
 | 
			
		||||
            var tester = new SingleStreamDataAdapterTester();
 | 
			
		||||
            tester.m_adapter = adapter;
 | 
			
		||||
            tester.m_bufferLength = bufferLength;
 | 
			
		||||
            var tester = new SingleStreamDataAdapterTester
 | 
			
		||||
            {
 | 
			
		||||
                m_adapter = adapter,
 | 
			
		||||
                m_bufferLength = bufferLength
 | 
			
		||||
            };
 | 
			
		||||
            adapter.SendCallBack = tester.SendCallback;
 | 
			
		||||
            adapter.ReceivedCallBack = tester.OnReceived;
 | 
			
		||||
            tester.m_receivedCallBack = receivedCallBack;
 | 
			
		||||
@@ -129,7 +131,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        {
 | 
			
		||||
            while (!this.m_dispose)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.tryGet(out var byteBlocks))
 | 
			
		||||
                if (this.TryGet(out var byteBlocks))
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var block in byteBlocks)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -163,7 +165,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.m_asyncBytes.Enqueue(asyncByte);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool tryGet(out List<ByteBlock> byteBlocks)
 | 
			
		||||
        private bool TryGet(out List<ByteBlock> byteBlocks)
 | 
			
		||||
        {
 | 
			
		||||
            byteBlocks = new List<ByteBlock>();
 | 
			
		||||
            ByteBlock block = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -70,10 +70,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public object Resolve(Type fromType, object[] ps = null, string key = "")
 | 
			
		||||
        public object Resolve(Type fromType, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (fromType == typeof(IContainer))
 | 
			
		||||
            {
 | 
			
		||||
@@ -108,11 +107,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                            {
 | 
			
		||||
                                if (descriptor.ToType.IsGenericType)
 | 
			
		||||
                                {
 | 
			
		||||
                                    return (descriptor.ToInstance = this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps));
 | 
			
		||||
                                    return (descriptor.ToInstance = this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments())));
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                {
 | 
			
		||||
                                    return (descriptor.ToInstance = this.Create(descriptor, descriptor.ToType, ps));
 | 
			
		||||
                                    return descriptor.ToInstance = this.Create(descriptor, descriptor.ToType);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
@@ -120,11 +119,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
 | 
			
		||||
                    if (descriptor.ToType.IsGenericType)
 | 
			
		||||
                    {
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps);
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()));
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType, ps);
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -143,10 +142,10 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                    }
 | 
			
		||||
                    lock (descriptor)
 | 
			
		||||
                    {
 | 
			
		||||
                        return descriptor.ToInstance ??= this.Create(descriptor, descriptor.ToType, ps);
 | 
			
		||||
                        return descriptor.ToInstance ??= this.Create(descriptor, descriptor.ToType);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return this.Create(descriptor, descriptor.ToType, ps);
 | 
			
		||||
                return this.Create(descriptor, descriptor.ToType);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -172,7 +171,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.m_registrations.TryRemove(k, out _);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private object Create(DependencyDescriptor descriptor, Type toType, object[] ops)
 | 
			
		||||
        private object Create(DependencyDescriptor descriptor, Type toType)
 | 
			
		||||
        {
 | 
			
		||||
            var ctor = toType.GetConstructors().FirstOrDefault(x => x.IsDefined(typeof(DependencyInjectAttribute), true));
 | 
			
		||||
            if (ctor is null)
 | 
			
		||||
@@ -198,28 +197,21 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            {
 | 
			
		||||
                for (var i = 0; i < parameters.Length; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (ops != null && ops.Length - 1 >= i)
 | 
			
		||||
                    if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
 | 
			
		||||
                    {
 | 
			
		||||
                        ps[i] = ops[i];
 | 
			
		||||
                        ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
 | 
			
		||||
                        if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
 | 
			
		||||
                        {
 | 
			
		||||
                            ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
 | 
			
		||||
                            var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                            var type = attribute.Type ?? parameters[i].ParameterType;
 | 
			
		||||
                            ps[i] = this.Resolve(type, attribute.Key);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
 | 
			
		||||
                            {
 | 
			
		||||
                                var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                                var type = attribute.Type ?? parameters[i].ParameterType;
 | 
			
		||||
                                ps[i] = this.Resolve(type, default, attribute.Key);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                ps[i] = this.Resolve(parameters[i].ParameterType, null);
 | 
			
		||||
                            }
 | 
			
		||||
                            ps[i] = this.Resolve(parameters[i].ParameterType, null);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -239,7 +231,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                        {
 | 
			
		||||
                            var attribute = item.GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                            var type = attribute.Type ?? item.PropertyType;
 | 
			
		||||
                            obj = this.Resolve(type, default, attribute.Key);
 | 
			
		||||
                            obj = this.Resolve(type, attribute.Key);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
@@ -259,28 +251,21 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                    ps = new object[parameters.Length];
 | 
			
		||||
                    for (var i = 0; i < ps.Length; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (ops != null && ops.Length - 1 >= i)
 | 
			
		||||
                        if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
 | 
			
		||||
                        {
 | 
			
		||||
                            ps[i] = ops[i];
 | 
			
		||||
                            ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
 | 
			
		||||
                            if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
 | 
			
		||||
                            {
 | 
			
		||||
                                ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
 | 
			
		||||
                                var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                                var type = attribute.Type ?? parameters[i].ParameterType;
 | 
			
		||||
                                ps[i] = this.Resolve(type, attribute.Key);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
 | 
			
		||||
                                {
 | 
			
		||||
                                    var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                                    var type = attribute.Type ?? parameters[i].ParameterType;
 | 
			
		||||
                                    ps[i] = this.Resolve(type, default, attribute.Key);
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                {
 | 
			
		||||
                                    ps[i] = this.Resolve(parameters[i].ParameterType, null);
 | 
			
		||||
                                }
 | 
			
		||||
                                ps[i] = this.Resolve(parameters[i].ParameterType, null);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 
 | 
			
		||||
@@ -381,35 +381,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T Resolve<T>(this IContainer container, object[] ps, string key = "")
 | 
			
		||||
        public static T Resolve<T>(this IContainer container, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            return (T)container.Resolve(typeof(T), ps, key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建类型对应的实例
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T Resolve<T>(this IContainer container)
 | 
			
		||||
        {
 | 
			
		||||
            return Resolve<T>(container, null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建类型对应的实例
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T Resolve<T>(this IContainer container, string key)
 | 
			
		||||
        {
 | 
			
		||||
            return Resolve<T>(container, null, key);
 | 
			
		||||
            return (T)container.Resolve(typeof(T), key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -461,7 +437,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                            {
 | 
			
		||||
                                var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                                var type = attribute.Type ?? parameters[i].ParameterType;
 | 
			
		||||
                                ps[i] = container.Resolve(type, default, attribute.Key);
 | 
			
		||||
                                ps[i] = container.Resolve(type, attribute.Key);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
@@ -489,47 +465,22 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            return (T)ResolveWithoutRoot(container, typeof(T));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///  尝试创建类型对应的实例,如果类型没有注册,则会返回null或者默认值类型。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T TryResolve<T>(this IContainer container, object[] ps, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            return (T)container.TryResolve(typeof(T), ps, key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///  尝试创建类型对应的实例,如果类型没有注册,则会返回null或者默认值类型。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static object TryResolve(this IContainer container, Type fromType, object[] ps, string key = "")
 | 
			
		||||
        public static object TryResolve(this IContainer container, Type fromType, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (container.IsRegistered(fromType))
 | 
			
		||||
            {
 | 
			
		||||
                return container.Resolve(fromType, ps, key);
 | 
			
		||||
                return container.Resolve(fromType, key);
 | 
			
		||||
            }
 | 
			
		||||
            return default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///  尝试创建类型对应的实例,如果类型没有注册,则会返回null或者默认值类型。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T TryResolve<T>(this IContainer container)
 | 
			
		||||
        {
 | 
			
		||||
            return TryResolve<T>(container, null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 尝试创建类型对应的实例,如果类型没有注册,则会返回null或者默认值类型。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -537,9 +488,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T TryResolve<T>(this IContainer container, string key)
 | 
			
		||||
        public static T TryResolve<T>(this IContainer container, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            return TryResolve<T>(container, null, key);
 | 
			
		||||
            return (T)TryResolve(container, typeof(T), key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion Resolve
 | 
			
		||||
 
 | 
			
		||||
@@ -34,10 +34,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// 创建目标类型的对应实例。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        object Resolve(Type fromType, object[] ps = null, string key = "");
 | 
			
		||||
        object Resolve(Type fromType, string key = "");
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 判断某类型是否已经注册
 | 
			
		||||
 
 | 
			
		||||
@@ -67,13 +67,13 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// <exception cref="Exception"></exception>
 | 
			
		||||
        public object Resolve(Type fromType, object[] ps = null, string key = "")
 | 
			
		||||
        public object Resolve(Type fromType, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (fromType.FullName == "ThingsGateway.Foundation.Core.IContainer")
 | 
			
		||||
            {
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.TryResolve(fromType, out var instance, ps, key))
 | 
			
		||||
            if (this.TryResolve(fromType, out var instance, key))
 | 
			
		||||
            {
 | 
			
		||||
                return instance;
 | 
			
		||||
            }
 | 
			
		||||
@@ -100,10 +100,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="instance"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected virtual bool TryResolve(Type fromType, out object instance, object[] ps = null, string key = "")
 | 
			
		||||
        protected virtual bool TryResolve(Type fromType, out object instance, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (key.IsNullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -182,7 +182,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
            if (!flag && !converter.CanConvertTo(destinationType))
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException("无法转换成类型:" + value.ToString() + "==>" + destinationType);
 | 
			
		||||
                throw new InvalidOperationException($"无法转换成类型:{value.ToString()}==>{destinationType}");
 | 
			
		||||
            }
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -190,7 +190,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException(" 类型转换出错:" + value.ToString() + "==>" + destinationType, e);
 | 
			
		||||
                throw new InvalidOperationException($" 类型转换出错:{value.ToString()}==>{destinationType}", e);
 | 
			
		||||
            }
 | 
			
		||||
            return returnValue;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -29,5 +32,46 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class TaskExtension
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 同步获取配置ConfigureAwait为false时的结果。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="task"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static T GetFalseAwaitResult<T>(this Task<T> task)
 | 
			
		||||
        {
 | 
			
		||||
            return task.ConfigureAwait(false).GetAwaiter().GetResult();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 同步配置ConfigureAwait为false时的执行。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="task"></param>
 | 
			
		||||
        public static void GetFalseAwaitResult(this Task task)
 | 
			
		||||
        {
 | 
			
		||||
            task.ConfigureAwait(false).GetAwaiter().GetResult();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 配置ConfigureAwait为false。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="task"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static ConfiguredTaskAwaitable<T> ConfigureFalseAwait<T>(this Task<T> task)
 | 
			
		||||
        {
 | 
			
		||||
            return task.ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 配置ConfigureAwait为false。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="task"></param>
 | 
			
		||||
        public static ConfiguredTaskAwaitable ConfigureFalseAwait(this Task task)
 | 
			
		||||
        {
 | 
			
		||||
            return task.ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -70,6 +70,15 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            return isPeriod;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 累计增加一个计数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public bool Increment()
 | 
			
		||||
        {
 | 
			
		||||
            return this.Increment(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重置<see cref="Count"/>和<see cref="LastIncrement"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -47,14 +47,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public TimeSpan Period { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重置<see cref="Count"/>和<see cref="LastIncrement"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Reset()
 | 
			
		||||
        {
 | 
			
		||||
            this.m_count = 0;
 | 
			
		||||
            this.m_lastIncrement = default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 累计增加计数
 | 
			
		||||
@@ -78,5 +71,26 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            Interlocked.Add(ref this.m_count, value);
 | 
			
		||||
            return isPeriod;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 累计增加一个计数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public bool Increment()
 | 
			
		||||
        {
 | 
			
		||||
            return this.Increment(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重置<see cref="Count"/>和<see cref="LastIncrement"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Reset()
 | 
			
		||||
        {
 | 
			
		||||
            this.m_count = 0;
 | 
			
		||||
            this.m_lastIncrement = default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -133,7 +133,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                fileStorage = null;
 | 
			
		||||
                msg = ex.Message;
 | 
			
		||||
                msg = ex.ToString();
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -134,7 +134,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                        string path = null;
 | 
			
		||||
                        while (true)
 | 
			
		||||
                        {
 | 
			
		||||
                            path = Path.Combine(dir, $"{count:0000}" + ".log");
 | 
			
		||||
                            path = Path.Combine(dir, $"{count:0000}.log");
 | 
			
		||||
                            if (!File.Exists(path))
 | 
			
		||||
                            {
 | 
			
		||||
                                this.m_writer = FilePool.GetWriter(path);
 | 
			
		||||
 
 | 
			
		||||
@@ -292,7 +292,13 @@ public static class LoggerExtensions
 | 
			
		||||
    {
 | 
			
		||||
        logger.Log(ThingsGateway.Foundation.Core.LogLevel.Error, null, msg, ex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 输出错误日志
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static void LogError(this ILog logger, Exception ex)
 | 
			
		||||
    {
 | 
			
		||||
        logger.Log(ThingsGateway.Foundation.Core.LogLevel.Error, null, ex.Message, ex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 输出警示日志
 | 
			
		||||
@@ -301,7 +307,13 @@ public static class LoggerExtensions
 | 
			
		||||
    {
 | 
			
		||||
        logger.Log(ThingsGateway.Foundation.Core.LogLevel.Warning, null, msg, ex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 输出警示日志
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static void LogWarning(this ILog logger, Exception ex)
 | 
			
		||||
    {
 | 
			
		||||
        logger.Log(ThingsGateway.Foundation.Core.LogLevel.Warning, null, ex.Message, ex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 输出警示日志
 | 
			
		||||
 
 | 
			
		||||
@@ -30,14 +30,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IPlugin : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 插件执行顺序
 | 
			
		||||
        /// <para>该属性值越大,越靠前执行。值相等时,按添加先后顺序</para>
 | 
			
		||||
        /// <para>该属性效果,仅在<see cref="IPluginsManager.Add(IPlugin)"/>之前设置有效。</para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [Obsolete("该属性已被弃用,插件顺序将直接由添加顺序决定。本设置将在正式版发布时直接删除", true)]
 | 
			
		||||
        int Order { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在插件被成功添加在<see cref="IPluginsManager"/>时执行。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class PluginBase : DisposableObject, IPlugin
 | 
			
		||||
    {
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        [Obsolete("该属性已被弃用,插件顺序将直接由添加顺序决定。本设置将在正式版发布时直接删除", true)]
 | 
			
		||||
        public int Order { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IPlugin.Loaded(IPluginsManager)"/>
 | 
			
		||||
        protected virtual void Loaded(IPluginsManager pluginsManager)
 | 
			
		||||
 
 | 
			
		||||
@@ -27,43 +27,48 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 请求关闭
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, string> OnClose { get; set; }
 | 
			
		||||
        public Func<DmtpActor, string, Task> Closed { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当创建通道时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, CreateChannelEventArgs> OnCreateChannel { get; set; }
 | 
			
		||||
        public Func<DmtpActor, CreateChannelEventArgs, Task> CreatedChannel { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 查找其他IDmtpActor
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<string, IDmtpActor> OnFindDmtpActor { get; set; }
 | 
			
		||||
        public Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在完成握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, DmtpVerifyEventArgs> OnHandshaked { get; set; }
 | 
			
		||||
        public Func<DmtpActor, DmtpVerifyEventArgs, Task> Handshaked { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 握手
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, DmtpVerifyEventArgs> OnHandshaking { get; set; }
 | 
			
		||||
        public Func<DmtpActor, DmtpVerifyEventArgs, Task> Handshaking { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重设Id
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, WaitSetId> OnResetId { get; set; }
 | 
			
		||||
        public Func<DmtpActor, IdChangedEventArgs, Task> IdChanged { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当需要路由的时候
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, PackageRouterEventArgs> OnRouting { get; set; }
 | 
			
		||||
        public Func<DmtpActor, PackageRouterEventArgs, Task> Routing { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据接口
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<DmtpActor, ArraySegment<byte>[]> OutputSend { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步发送数据接口
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<DmtpActor, ArraySegment<byte>[], Task> OutputSendAsync { get; set; }
 | 
			
		||||
 | 
			
		||||
        #endregion 委托
 | 
			
		||||
 | 
			
		||||
        #region 属性
 | 
			
		||||
@@ -119,29 +124,22 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual void Close(bool sendClose, string message)
 | 
			
		||||
        public void Close(string msg)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnClosed(true, msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public bool SendClose(string msg)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        if (sendClose)
 | 
			
		||||
                        {
 | 
			
		||||
                            this.SendString(0, message);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                    }
 | 
			
		||||
                    this.IsHandshaked = false;
 | 
			
		||||
                    this.WaitHandlePool.CancelAll();
 | 
			
		||||
                    this.OnClose?.Invoke(this, message);
 | 
			
		||||
                }
 | 
			
		||||
                this.SendString(0, msg);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -165,7 +163,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                Metadata = metadata
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.OnHandshaking?.Invoke(this, args);
 | 
			
		||||
            this.OnHandshaking(args).GetFalseAwaitResult();
 | 
			
		||||
 | 
			
		||||
            var waitVerify = new WaitVerify()
 | 
			
		||||
            {
 | 
			
		||||
@@ -189,7 +187,8 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            {
 | 
			
		||||
                                this.Id = verifyResult.Id;
 | 
			
		||||
                                this.IsHandshaked = true;
 | 
			
		||||
                                this.PrivateHandshaked(new DmtpVerifyEventArgs()
 | 
			
		||||
 | 
			
		||||
                                Task.Factory.StartNew(this.PrivateOnHandshaked, new DmtpVerifyEventArgs()
 | 
			
		||||
                                {
 | 
			
		||||
                                    Id = verifyResult.Id,
 | 
			
		||||
                                    Metadata = verifyResult.Metadata,
 | 
			
		||||
@@ -201,18 +200,15 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                verifyResult.Handle = true;
 | 
			
		||||
                                this.Close(false, verifyResult.Message);
 | 
			
		||||
                                throw new TokenVerifyException(verifyResult.Message);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    case WaitDataStatus.Overtime:
 | 
			
		||||
                        this.Close(false, TouchSocketDmtpStatus.Overtime.GetDescription());
 | 
			
		||||
                        throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription());
 | 
			
		||||
                    case WaitDataStatus.Canceled:
 | 
			
		||||
                    case WaitDataStatus.Disposed:
 | 
			
		||||
                    default:
 | 
			
		||||
                        this.Close(false, null);
 | 
			
		||||
                        return;
 | 
			
		||||
                        throw new OperationCanceledException();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
@@ -240,7 +236,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                Metadata = metadata
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.OnHandshaking?.Invoke(this, args);
 | 
			
		||||
            await this.OnHandshaking(args).ConfigureFalseAwait();
 | 
			
		||||
 | 
			
		||||
            var waitVerify = new WaitVerify()
 | 
			
		||||
            {
 | 
			
		||||
@@ -253,8 +249,8 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.SendJsonObject(P1_Handshake_Request, waitVerify);
 | 
			
		||||
                switch (await waitData.WaitAsync(timeout))
 | 
			
		||||
                await this.SendJsonObjectAsync(P1_Handshake_Request, waitVerify).ConfigureFalseAwait();
 | 
			
		||||
                switch (await waitData.WaitAsync(timeout).ConfigureFalseAwait())
 | 
			
		||||
                {
 | 
			
		||||
                    case WaitDataStatus.SetRunning:
 | 
			
		||||
                        {
 | 
			
		||||
@@ -263,7 +259,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            {
 | 
			
		||||
                                this.Id = verifyResult.Id;
 | 
			
		||||
                                this.IsHandshaked = true;
 | 
			
		||||
                                this.PrivateHandshaked(new DmtpVerifyEventArgs()
 | 
			
		||||
                                _ = Task.Factory.StartNew(this.PrivateOnHandshaked, new DmtpVerifyEventArgs()
 | 
			
		||||
                                {
 | 
			
		||||
                                    Id = verifyResult.Id,
 | 
			
		||||
                                    Metadata = verifyResult.Metadata,
 | 
			
		||||
@@ -275,18 +271,15 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                verifyResult.Handle = true;
 | 
			
		||||
                                this.Close(false, verifyResult.Message);
 | 
			
		||||
                                throw new TokenVerifyException(verifyResult.Message);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    case WaitDataStatus.Overtime:
 | 
			
		||||
                        this.Close(false, TouchSocketDmtpStatus.Overtime.GetDescription());
 | 
			
		||||
                        throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription());
 | 
			
		||||
                    case WaitDataStatus.Canceled:
 | 
			
		||||
                    case WaitDataStatus.Disposed:
 | 
			
		||||
                    default:
 | 
			
		||||
                        this.Close(false, null);
 | 
			
		||||
                        return;
 | 
			
		||||
                        throw new OperationCanceledException();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
@@ -295,6 +288,100 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 委托触发
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当关闭后
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="manual"></param>
 | 
			
		||||
        /// <param name="msg"></param>
 | 
			
		||||
        protected virtual Task OnClosed(bool manual, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                this.IsHandshaked = false;
 | 
			
		||||
                this.WaitHandlePool.CancelAll();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (manual)
 | 
			
		||||
            {
 | 
			
		||||
                return EasyTask.CompletedTask;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.Closed != null)
 | 
			
		||||
            {
 | 
			
		||||
                return this.Closed.Invoke(this, msg);
 | 
			
		||||
            }
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 正在握手连接
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected virtual Task OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Handshaking != null)
 | 
			
		||||
            {
 | 
			
		||||
                return this.Handshaking.Invoke(this, e);
 | 
			
		||||
            }
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 握手连接完成
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected virtual Task OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Handshaked != null)
 | 
			
		||||
            {
 | 
			
		||||
                return this.Handshaked.Invoke(this, e);
 | 
			
		||||
            }
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当Id修改时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected virtual Task OnIdChanged(IdChangedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IdChanged != null)
 | 
			
		||||
            {
 | 
			
		||||
                return this.IdChanged.Invoke(this, e);
 | 
			
		||||
            }
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当完成创建通道时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected virtual Task OnCreatedChannel(CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.CreatedChannel != null)
 | 
			
		||||
            {
 | 
			
		||||
                return this.CreatedChannel.Invoke(this, e);
 | 
			
		||||
            }
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void PrivateOnHandshaked(object obj)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked((DmtpVerifyEventArgs)obj);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void PrivateOnCreatedChannel(object obj)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreatedChannel((CreateChannelEventArgs)obj);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region const
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -368,7 +455,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public virtual bool InputReceivedData(DmtpMessage message)
 | 
			
		||||
        public virtual async Task<bool> InputReceivedData(DmtpMessage message)
 | 
			
		||||
        {
 | 
			
		||||
            this.LastActiveTime = DateTime.Now;
 | 
			
		||||
            var byteBlock = message.BodyByteBlock;
 | 
			
		||||
@@ -376,7 +463,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            {
 | 
			
		||||
                case P0_Close:
 | 
			
		||||
                    {
 | 
			
		||||
                        this.Close(false, message.GetBodyString());
 | 
			
		||||
                        _ = this.OnClosed(false, message.GetBodyString());
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                case P1_Handshake_Request:
 | 
			
		||||
@@ -391,11 +478,11 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                                Metadata = waitVerify.Metadata,
 | 
			
		||||
                                Id = waitVerify.Id,
 | 
			
		||||
                            };
 | 
			
		||||
                            this.OnHandshaking?.Invoke(this, args);
 | 
			
		||||
                            await this.OnHandshaking(args).ConfigureFalseAwait();
 | 
			
		||||
 | 
			
		||||
                            if (args.Id.HasValue())
 | 
			
		||||
                            {
 | 
			
		||||
                                this.OnResetId?.Invoke(this, new WaitSetId(this.Id, args.Id));
 | 
			
		||||
                                await this.OnIdChanged(new IdChangedEventArgs(this.Id, args.Id)).ConfigureFalseAwait();
 | 
			
		||||
                                this.Id = args.Id;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
@@ -403,24 +490,23 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            {
 | 
			
		||||
                                waitVerify.Id = this.Id;
 | 
			
		||||
                                waitVerify.Status = 1;
 | 
			
		||||
                                this.SendJsonObject(P2_Handshake_Response, waitVerify);
 | 
			
		||||
                                await this.SendJsonObjectAsync(P2_Handshake_Response, waitVerify).ConfigureFalseAwait();
 | 
			
		||||
                                this.IsHandshaked = true;
 | 
			
		||||
                                args.Message = "Success";
 | 
			
		||||
 | 
			
		||||
                                Task.Factory.StartNew(this.PrivateHandshaked, args);
 | 
			
		||||
                                _ = Task.Factory.StartNew(this.PrivateOnHandshaked, args);
 | 
			
		||||
                            }
 | 
			
		||||
                            else//不允许连接
 | 
			
		||||
                            {
 | 
			
		||||
                                waitVerify.Status = 2;
 | 
			
		||||
                                waitVerify.Message = args.Message;
 | 
			
		||||
                                this.SendJsonObject(P2_Handshake_Response, waitVerify);
 | 
			
		||||
                                this.Close(false, args.Message);
 | 
			
		||||
                                await this.SendJsonObjectAsync(P2_Handshake_Response, waitVerify).ConfigureFalseAwait();
 | 
			
		||||
                                _ = this.OnClosed(false, args.Message);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            this.Logger.Error(this, $"在protocol={message.ProtocolFlags}中发生错误。信息:{ex.Message}");
 | 
			
		||||
                            this.Close(false, ex.Message);
 | 
			
		||||
                            _ = this.OnClosed(false, ex.Message);
 | 
			
		||||
                        }
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -449,7 +535,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            var waitSetId = this.ResolveJsonObject<WaitSetId>(message.GetBodyString());
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                this.OnResetId?.Invoke(this, waitSetId);
 | 
			
		||||
                                await this.OnIdChanged(new IdChangedEventArgs(waitSetId.OldId, waitSetId.NewId)).ConfigureFalseAwait();
 | 
			
		||||
                                this.Id = waitSetId.NewId;
 | 
			
		||||
                                waitSetId.Status = 1;
 | 
			
		||||
                            }
 | 
			
		||||
@@ -458,7 +544,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                                waitSetId.Status = 2;
 | 
			
		||||
                                waitSetId.Message = ex.Message;
 | 
			
		||||
                            }
 | 
			
		||||
                            this.SendJsonObject(P4_ResetId_Response, waitSetId);
 | 
			
		||||
                            await this.SendJsonObjectAsync(P4_ResetId_Response, waitSetId).ConfigureFalseAwait();
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
@@ -486,11 +572,12 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
                            if (this.AllowRoute && waitPing.Route)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (this.TryRoute(RouteType.Ping, waitPing))
 | 
			
		||||
 | 
			
		||||
                                if (await this.TryRoute(new PackageRouterEventArgs(RouteType.Ping, waitPing)).ConfigureFalseAwait())
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (this.TryFindDmtpActor(waitPing.TargetId, out var actor))
 | 
			
		||||
                                    if (await this.TryFindDmtpActor(waitPing.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        actor.Send(P5_Ping_Request, byteBlock);
 | 
			
		||||
                                        await actor.SendAsync(P5_Ping_Request, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                                        return true;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
@@ -508,7 +595,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                                waitPing.Status = TouchSocketDmtpStatus.Success.ToValue();
 | 
			
		||||
                            }
 | 
			
		||||
                            waitPing.SwitchId();
 | 
			
		||||
                            this.SendJsonObject(P6_Ping_Response, waitPing);
 | 
			
		||||
                            await this.SendJsonObjectAsync(P6_Ping_Response, waitPing).ConfigureFalseAwait();
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
@@ -524,9 +611,9 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
                            if (this.AllowRoute && waitPing.Route)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (this.TryFindDmtpActor(waitPing.TargetId, out var actor))
 | 
			
		||||
                                if (await this.TryFindDmtpActor(waitPing.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                                {
 | 
			
		||||
                                    actor.Send(P6_Ping_Response, byteBlock);
 | 
			
		||||
                                    await actor.SendAsync(P6_Ping_Response, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
@@ -548,11 +635,11 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            waitCreateChannel.UnpackageRouter(byteBlock);
 | 
			
		||||
                            if (this.AllowRoute && waitCreateChannel.Route)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (this.TryRoute(RouteType.CreateChannel, waitCreateChannel))
 | 
			
		||||
                                if (await this.TryRoute(new PackageRouterEventArgs(RouteType.CreateChannel, waitCreateChannel)).ConfigureFalseAwait())
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (this.TryFindDmtpActor(waitCreateChannel.TargetId, out var actor))
 | 
			
		||||
                                    if (await this.TryFindDmtpActor(waitCreateChannel.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        actor.Send(P7_CreateChannel_Request, byteBlock);
 | 
			
		||||
                                        await actor.SendAsync(P7_CreateChannel_Request, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                                        return true;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
@@ -593,7 +680,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            waitCreateChannel.SwitchId();
 | 
			
		||||
                            byteBlock.Reset();
 | 
			
		||||
                            waitCreateChannel.Package(byteBlock);
 | 
			
		||||
                            this.Send(P8_CreateChannel_Response, byteBlock);
 | 
			
		||||
                            await this.SendAsync(P8_CreateChannel_Response, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
@@ -609,9 +696,9 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            waitCreateChannel.UnpackageRouter(byteBlock);
 | 
			
		||||
                            if (this.AllowRoute && waitCreateChannel.Route)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (this.TryFindDmtpActor(waitCreateChannel.TargetId, out var actor))
 | 
			
		||||
                                if (await this.TryFindDmtpActor(waitCreateChannel.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                                {
 | 
			
		||||
                                    actor.Send(P8_CreateChannel_Response, byteBlock);
 | 
			
		||||
                                    await actor.SendAsync(P8_CreateChannel_Response, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                                    return true;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
@@ -635,9 +722,9 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                            channelPackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                            if (this.AllowRoute && channelPackage.Route)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (this.TryFindDmtpActor(channelPackage.TargetId, out var actor))
 | 
			
		||||
                                if (await this.TryFindDmtpActor(channelPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                                {
 | 
			
		||||
                                    actor.Send(P9_ChannelPackage, byteBlock);
 | 
			
		||||
                                    await actor.SendAsync(P9_ChannelPackage, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                {
 | 
			
		||||
@@ -648,7 +735,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                                    channelPackage.DataType = ChannelDataType.DisposeOrder;
 | 
			
		||||
                                    byteBlock.Reset();
 | 
			
		||||
                                    channelPackage.Package(byteBlock);
 | 
			
		||||
                                    this.Send(P9_ChannelPackage, byteBlock);
 | 
			
		||||
                                    await this.SendAsync(P9_ChannelPackage, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
@@ -683,7 +770,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual bool Ping(string targetId, int timeout = 5000)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor))
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId).GetFalseAwaitResult() is DmtpActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.Ping(timeout);
 | 
			
		||||
            }
 | 
			
		||||
@@ -697,15 +784,15 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual Task<bool> PingAsync(string targetId, int timeout = 5000)
 | 
			
		||||
        public virtual async Task<bool> PingAsync(string targetId, int timeout = 5000)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor))
 | 
			
		||||
            if (this.AllowRoute && await this.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.PingAsync(timeout);
 | 
			
		||||
                return await actor.PingAsync(timeout).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return this.PrivatePingAsync(targetId, timeout);
 | 
			
		||||
                return await this.PrivatePingAsync(targetId, timeout).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -724,7 +811,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                    {
 | 
			
		||||
                        if (waitData.WaitResult.Status == 1)
 | 
			
		||||
                        {
 | 
			
		||||
                            this.OnResetId?.Invoke(this, new WaitSetId(this.Id, id));
 | 
			
		||||
                            this.OnIdChanged(new IdChangedEventArgs(this.Id, id)).GetFalseAwaitResult();
 | 
			
		||||
                            this.Id = id;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
@@ -754,13 +841,13 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
            this.SendJsonObject(P3_ResetId_Request, waitSetId);
 | 
			
		||||
 | 
			
		||||
            switch (await waitData.WaitAsync(5000))
 | 
			
		||||
            switch (await waitData.WaitAsync(5000).ConfigureFalseAwait())
 | 
			
		||||
            {
 | 
			
		||||
                case WaitDataStatus.SetRunning:
 | 
			
		||||
                    {
 | 
			
		||||
                        if (waitData.WaitResult.Status == 1)
 | 
			
		||||
                        {
 | 
			
		||||
                            this.OnResetId?.Invoke(this, new WaitSetId(this.Id, id));
 | 
			
		||||
                            await this.OnIdChanged(new IdChangedEventArgs(this.Id, id)).ConfigureFalseAwait();
 | 
			
		||||
                            this.Id = id;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
@@ -801,6 +888,17 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.Send(protocol, bytes, 0, bytes.Length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task SendJsonObjectAsync<T>(ushort protocol, in T obj)
 | 
			
		||||
        {
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
            var bytes = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(obj, typeof(T), TouchSokcetDmtpSourceGenerationContext.Default);
 | 
			
		||||
#else
 | 
			
		||||
            var bytes = SerializeConvert.JsonSerializeToBytes(obj);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            return this.SendAsync(protocol, bytes, 0, bytes.Length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private T ResolveJsonObject<T>(string json)
 | 
			
		||||
        {
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
@@ -836,31 +934,34 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual bool TryFindDmtpActor(string targetId, out DmtpActor actor)
 | 
			
		||||
        public virtual async Task<DmtpActor> TryFindDmtpActor(string targetId)
 | 
			
		||||
        {
 | 
			
		||||
            if (targetId == this.Id)
 | 
			
		||||
            {
 | 
			
		||||
                actor = this;
 | 
			
		||||
                return true;
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.OnFindDmtpActor?.Invoke(targetId) is DmtpActor newActor)
 | 
			
		||||
            if (this.FindDmtpActor != null)
 | 
			
		||||
            {
 | 
			
		||||
                actor = newActor;
 | 
			
		||||
                return true;
 | 
			
		||||
                if (await this.FindDmtpActor.Invoke(targetId).ConfigureFalseAwait() is DmtpActor newActor)
 | 
			
		||||
                {
 | 
			
		||||
                    return newActor;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            actor = default;
 | 
			
		||||
            return false;
 | 
			
		||||
            return default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual bool TryRoute(RouteType routerType, RouterPackage routerPackage)
 | 
			
		||||
        public virtual async Task<bool> TryRoute(PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var args = new PackageRouterEventArgs(routerType, routerPackage);
 | 
			
		||||
                this.OnRouting?.Invoke(this, args);
 | 
			
		||||
                return args.IsPermitOperation;
 | 
			
		||||
                if (this.Routing != null)
 | 
			
		||||
                {
 | 
			
		||||
                    await this.Routing.Invoke(this, e).ConfigureFalseAwait();
 | 
			
		||||
                    return e.IsPermitOperation;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
@@ -868,27 +969,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual bool TryRoute(RouteType routerType, WaitRouterPackage routerPackage)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var args = new PackageRouterEventArgs(routerType, routerPackage);
 | 
			
		||||
                this.OnRouting?.Invoke(this, args);
 | 
			
		||||
                routerPackage.Message = args.Message;
 | 
			
		||||
                return args.IsPermitOperation;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void PrivateHandshaked(object obj)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked?.Invoke(this, (DmtpVerifyEventArgs)obj);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool PrivatePing(string targetId, int timeout)
 | 
			
		||||
        {
 | 
			
		||||
            var waitPing = new WaitPing
 | 
			
		||||
@@ -942,7 +1022,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.SendJsonObject(P5_Ping_Request, waitPing);
 | 
			
		||||
                switch (await waitData.WaitAsync(timeout))
 | 
			
		||||
                switch (await waitData.WaitAsync(timeout).ConfigureFalseAwait())
 | 
			
		||||
                {
 | 
			
		||||
                    case WaitDataStatus.SetRunning:
 | 
			
		||||
                        {
 | 
			
		||||
@@ -979,16 +1059,15 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <param name="disposing"></param>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnClose = null;
 | 
			
		||||
            this.OnRouting = null;
 | 
			
		||||
            this.OnFindDmtpActor = null;
 | 
			
		||||
            this.OnHandshaked = null;
 | 
			
		||||
            this.OnHandshaking = null;
 | 
			
		||||
            this.OnResetId = null;
 | 
			
		||||
 | 
			
		||||
            this.Closed = null;
 | 
			
		||||
            this.Routing = null;
 | 
			
		||||
            this.FindDmtpActor = null;
 | 
			
		||||
            this.Handshaked = null;
 | 
			
		||||
            this.Handshaking = null;
 | 
			
		||||
            this.IdChanged = null;
 | 
			
		||||
            this.OutputSend = null;
 | 
			
		||||
            this.OnClosed(true, nameof(Dispose));
 | 
			
		||||
            this.WaitHandlePool.SafeDispose();
 | 
			
		||||
            this.Close(false, nameof(Dispose));
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1005,7 +1084,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(length)),
 | 
			
		||||
            new ArraySegment<byte>(buffer,offset,length)
 | 
			
		||||
           };
 | 
			
		||||
            this.OutputSend?.Invoke(this, transferBytes);
 | 
			
		||||
            this.OutputSend.Invoke(this, transferBytes);
 | 
			
		||||
            this.LastActiveTime = DateTime.Now;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1022,10 +1101,20 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual Task SendAsync(ushort protocol, byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return Task.Run(() =>
 | 
			
		||||
            var transferBytes = new ArraySegment<byte>[]
 | 
			
		||||
            {
 | 
			
		||||
                this.Send(protocol, buffer, offset, length);
 | 
			
		||||
            });
 | 
			
		||||
            new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(protocol)),
 | 
			
		||||
            new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(length)),
 | 
			
		||||
            new ArraySegment<byte>(buffer,offset,length)
 | 
			
		||||
            };
 | 
			
		||||
            this.LastActiveTime = DateTime.Now;
 | 
			
		||||
            return this.OutputSendAsync.Invoke(this, transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual Task SendAsync(ushort protocol, ByteBlock byteBlock)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendAsync(protocol, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 协议异步发送
 | 
			
		||||
@@ -1059,7 +1148,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId));
 | 
			
		||||
            }
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor))
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId).GetFalseAwaitResult() is DmtpActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.CreateChannel(id, metadata);
 | 
			
		||||
            }
 | 
			
		||||
@@ -1077,7 +1166,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor))
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId).GetFalseAwaitResult() is DmtpActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.CreateChannel(metadata);
 | 
			
		||||
            }
 | 
			
		||||
@@ -1100,37 +1189,37 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual Task<IDmtpChannel> CreateChannelAsync(string targetId, int id, Metadata metadata = default)
 | 
			
		||||
        public virtual async Task<IDmtpChannel> CreateChannelAsync(string targetId, int id, Metadata metadata = default)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(targetId))
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId));
 | 
			
		||||
            }
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor))
 | 
			
		||||
            if (this.AllowRoute && await this.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.CreateChannelAsync(id, metadata);
 | 
			
		||||
                return await actor.CreateChannelAsync(id, metadata).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return this.PrivateCreateChannelAsync(targetId, false, id, metadata);
 | 
			
		||||
                return await this.PrivateCreateChannelAsync(targetId, false, id, metadata).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual Task<IDmtpChannel> CreateChannelAsync(string targetId, Metadata metadata = default)
 | 
			
		||||
        public virtual async Task<IDmtpChannel> CreateChannelAsync(string targetId, Metadata metadata = default)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(targetId))
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.AllowRoute && this.TryFindDmtpActor(targetId, out var actor))
 | 
			
		||||
            if (this.AllowRoute && await this.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.CreateChannelAsync(metadata);
 | 
			
		||||
                return await actor.CreateChannelAsync(metadata).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return this.PrivateCreateChannelAsync(targetId, true, 0, metadata);
 | 
			
		||||
                return await this.PrivateCreateChannelAsync(targetId, true, 0, metadata).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1208,9 +1297,14 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                                        var channel = new InternalChannel(this, targetId, result.Metadata);
 | 
			
		||||
                                        channel.SetId(result.ChannelId);
 | 
			
		||||
                                        channel.SetUsing();
 | 
			
		||||
                                        return this.m_userChannels.TryAdd(result.ChannelId, channel)
 | 
			
		||||
                                            ? (IDmtpChannel)channel
 | 
			
		||||
                                            : throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription());
 | 
			
		||||
                                        if (this.m_userChannels.TryAdd(result.ChannelId, channel))
 | 
			
		||||
                                        {
 | 
			
		||||
                                            return channel;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        else
 | 
			
		||||
                                        {
 | 
			
		||||
                                            throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription());
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                case TouchSocketDmtpStatus.ClientNotFind:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -1269,8 +1363,8 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                waitCreateChannel.Package(byteBlock);
 | 
			
		||||
                this.Send(P7_CreateChannel_Request, byteBlock);
 | 
			
		||||
                switch (await waitData.WaitAsync(10 * 1000))
 | 
			
		||||
                await this.SendAsync(P7_CreateChannel_Request, byteBlock).ConfigureFalseAwait();
 | 
			
		||||
                switch (await waitData.WaitAsync(10 * 1000).ConfigureFalseAwait())
 | 
			
		||||
                {
 | 
			
		||||
                    case WaitDataStatus.SetRunning:
 | 
			
		||||
                        {
 | 
			
		||||
@@ -1282,9 +1376,14 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                                        var channel = new InternalChannel(this, targetId, result.Metadata);
 | 
			
		||||
                                        channel.SetId(result.ChannelId);
 | 
			
		||||
                                        channel.SetUsing();
 | 
			
		||||
                                        return this.m_userChannels.TryAdd(result.ChannelId, channel)
 | 
			
		||||
                                            ? (IDmtpChannel)channel
 | 
			
		||||
                                            : throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription());
 | 
			
		||||
                                        if (this.m_userChannels.TryAdd(result.ChannelId, channel))
 | 
			
		||||
                                        {
 | 
			
		||||
                                            return channel;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        else
 | 
			
		||||
                                        {
 | 
			
		||||
                                            throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription());
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                case TouchSocketDmtpStatus.ClientNotFind:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -1333,7 +1432,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                channel.SetId(id);
 | 
			
		||||
                if (this.m_userChannels.TryAdd(id, channel))
 | 
			
		||||
                {
 | 
			
		||||
                    Task.Factory.StartNew(this.ThisRequestCreateChannel, new CreateChannelEventArgs(id, metadata));
 | 
			
		||||
                    Task.Factory.StartNew(this.PrivateOnCreatedChannel, new CreateChannelEventArgs(id, metadata));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
@@ -1344,16 +1443,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisRequestCreateChannel(object state)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.OnCreateChannel?.Invoke(this, (CreateChannelEventArgs)state);
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion IDmtpChannel
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -152,9 +152,8 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 关闭
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="sendClose">是否发送close报文</param>
 | 
			
		||||
        /// <param name="message">传递消息</param>
 | 
			
		||||
        void Close(bool sendClose, string message);
 | 
			
		||||
        void Close(string message);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 向当前对点发送一个Ping报文,并且等待回应。
 | 
			
		||||
@@ -226,6 +225,14 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <param name="length"></param>
 | 
			
		||||
        Task SendAsync(ushort protocol, byte[] buffer, int offset, int length);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步发送字节块
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="protocol"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        Task SendAsync(ushort protocol, ByteBlock byteBlock);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 以Fast序列化,发送小(64K)对象。接收方需要使用ReadObject读取对象。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -260,25 +267,20 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// 尝试获取指定Id的DmtpActor。一般此方法仅在Service下有效。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="targetId"></param>
 | 
			
		||||
        /// <param name="actor"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        bool TryFindDmtpActor(string targetId, out DmtpActor actor);
 | 
			
		||||
        Task<DmtpActor> TryFindDmtpActor(string targetId);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 尝试请求路由,触发路由相关插件。
 | 
			
		||||
        /// 尝试请求路由,触发路由相关插件。并在路由失败时向<see cref="MsgPermitEventArgs.Message"/>中传递消息。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="routerType"></param>
 | 
			
		||||
        /// <param name="routerPackage"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        bool TryRoute(RouteType routerType, RouterPackage routerPackage);
 | 
			
		||||
        Task<bool> TryRoute(PackageRouterEventArgs e);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 尝试请求路由,触发路由相关插件。并在路由失败时向<see cref="MsgRouterPackage.Message"/>中传递消息。
 | 
			
		||||
        /// 发送Close请求
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="routerType"></param>
 | 
			
		||||
        /// <param name="routerPackage"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        bool TryRoute(RouteType routerType, WaitRouterPackage routerPackage);
 | 
			
		||||
        /// <param name="msg"></param>
 | 
			
		||||
        bool SendClose(string msg);
 | 
			
		||||
 | 
			
		||||
        #endregion 方法
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,12 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -17,17 +23,22 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class TcpDmtpAdapter : CustomFixedHeaderByteBlockDataHandlingAdapter<DmtpMessage>
 | 
			
		||||
    {
 | 
			
		||||
        private SpinLock m_locker = new SpinLock();
 | 
			
		||||
        private readonly SemaphoreSlim m_locker = new SemaphoreSlim(1, 1);
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CanSendRequestInfo => true;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CanSplicingSend => false;
 | 
			
		||||
        public override bool CanSplicingSend => true;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override int HeaderLength => 6;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 最大拼接
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public const int MaxSplicing = 1024 * 64;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override DmtpMessage GetInstance()
 | 
			
		||||
        {
 | 
			
		||||
@@ -40,6 +51,25 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            request.SafeDispose();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            if (!(requestInfo is DmtpMessage message))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法将{nameof(requestInfo)}转换为{nameof(DmtpMessage)}");
 | 
			
		||||
            }
 | 
			
		||||
            if (message.BodyByteBlock != null && message.BodyByteBlock.Length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送的BodyLength={requestInfo.BodyLength},大于设定的MaxPackageSize={this.MaxPackageSize}");
 | 
			
		||||
            }
 | 
			
		||||
            using (var byteBlock = new ByteBlock(message.GetLength()))
 | 
			
		||||
            {
 | 
			
		||||
                message.Build(byteBlock);
 | 
			
		||||
                await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void PreviewSend(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
@@ -58,6 +88,54 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            if (transferBytes.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var length = 0;
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            {
 | 
			
		||||
                length += item.Count;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
 | 
			
		||||
            }
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
 | 
			
		||||
                    await this.m_locker.WaitAsync();
 | 
			
		||||
                    foreach (var item in transferBytes)
 | 
			
		||||
                    {
 | 
			
		||||
                        await this.GoSendAsync(item.Array, item.Offset, item.Count);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    this.m_locker.Release();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock(length))
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var item in transferBytes)
 | 
			
		||||
                    {
 | 
			
		||||
                        byteBlock.Write(item.Array, item.Offset, item.Count);
 | 
			
		||||
                    }
 | 
			
		||||
                    await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void PreviewSend(IList<ArraySegment<byte>> transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
@@ -77,20 +155,31 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var lockTaken = false;
 | 
			
		||||
            try
 | 
			
		||||
            if (length > this.MaxPackageSize)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_locker.Enter(ref lockTaken);
 | 
			
		||||
                foreach (var item in transferBytes)
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    this.GoSend(item.Array, item.Offset, item.Count);
 | 
			
		||||
 | 
			
		||||
                    this.m_locker.Wait();
 | 
			
		||||
                    foreach (var item in transferBytes)
 | 
			
		||||
                    {
 | 
			
		||||
                        this.GoSend(item.Array, item.Offset, item.Count);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    this.m_locker.Release();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (lockTaken)
 | 
			
		||||
                using (var byteBlock = new ByteBlock(length))
 | 
			
		||||
                {
 | 
			
		||||
                    this.m_locker.Exit(false);
 | 
			
		||||
                    foreach (var item in transferBytes)
 | 
			
		||||
                    {
 | 
			
		||||
                        byteBlock.Write(item.Array, item.Offset, item.Count);
 | 
			
		||||
                    }
 | 
			
		||||
                    this.GoSend(byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private DmtpActor m_smtpActor;
 | 
			
		||||
        private Func<string, Task<IDmtpActor>> m_findDmtpActor;
 | 
			
		||||
        private DmtpActor m_dmtpActor;
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +45,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_dmtpActor; }
 | 
			
		||||
 | 
			
		||||
        #region 连接
 | 
			
		||||
 | 
			
		||||
@@ -78,7 +78,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                if (response.StatusCode == 101)
 | 
			
		||||
                {
 | 
			
		||||
                    this.SwitchProtocolToDmtp();
 | 
			
		||||
                    this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                        this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
 | 
			
		||||
                        timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
 | 
			
		||||
                    return this;
 | 
			
		||||
@@ -114,7 +114,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                if (response.StatusCode == 101)
 | 
			
		||||
                {
 | 
			
		||||
                    this.SwitchProtocolToDmtp();
 | 
			
		||||
                    this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                        this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
 | 
			
		||||
                        timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token);
 | 
			
		||||
                    return this;
 | 
			
		||||
@@ -156,7 +156,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                if (response.StatusCode == 101)
 | 
			
		||||
                {
 | 
			
		||||
                    this.SwitchProtocolToDmtp();
 | 
			
		||||
                    await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                         this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
 | 
			
		||||
                         timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
 | 
			
		||||
                    return this;
 | 
			
		||||
@@ -197,7 +197,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                if (response.StatusCode == 101)
 | 
			
		||||
                {
 | 
			
		||||
                    this.SwitchProtocolToDmtp();
 | 
			
		||||
                    await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                         this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
 | 
			
		||||
                         timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token);
 | 
			
		||||
                    return this;
 | 
			
		||||
@@ -215,28 +215,53 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #endregion 连接
 | 
			
		||||
 | 
			
		||||
        #region 断开
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.SafeDispose();
 | 
			
		||||
            this.m_dmtpActor?.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="msg"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message)
 | 
			
		||||
            if (this.m_dmtpActor != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
                this.m_dmtpActor.SendClose(msg);
 | 
			
		||||
                this.m_dmtpActor.Close(msg);
 | 
			
		||||
            }
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_dmtpActor?.Close(e.Message);
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message)
 | 
			
		||||
            {
 | 
			
		||||
                if (!await this.m_dmtpActor.InputReceivedData(message))
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.PluginsManager.Enable)
 | 
			
		||||
                    {
 | 
			
		||||
                        this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                        await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return base.HandleReceivedData(byteBlock, requestInfo);
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
@@ -250,25 +275,19 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
            this.DmtpActor.Close(false, e.Message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region ResetId
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetId(string)"/>
 | 
			
		||||
        public void ResetId(string id)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.ResetId(id);
 | 
			
		||||
            this.m_dmtpActor.ResetId(id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/>
 | 
			
		||||
        public Task ResetIdAsync(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            return this.m_smtpActor.ResetIdAsync(newId);
 | 
			
		||||
            return this.m_dmtpActor.ResetIdAsync(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion ResetId
 | 
			
		||||
@@ -277,72 +296,47 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        {
 | 
			
		||||
            this.Protocol = DmtpUtility.DmtpProtocol;
 | 
			
		||||
            this.SetDataHandlingAdapter(new TcpDmtpAdapter());
 | 
			
		||||
            this.m_smtpActor = new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            this.m_dmtpActor = new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                OutputSend = DmtpActorSend,
 | 
			
		||||
                OnRouting = OnDmtpActorRouting,
 | 
			
		||||
                OnHandshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                OnHandshaked = OnDmtpActorHandshaked,
 | 
			
		||||
                OnClose = OnDmtpActorClose,
 | 
			
		||||
                OnCreateChannel = this.OnDmtpActorCreateChannel,
 | 
			
		||||
                OutputSend = this.DmtpActorSend,
 | 
			
		||||
                OutputSendAsync = this.DmtpActorSendAsync,
 | 
			
		||||
                Routing = this.OnDmtpActorRouting,
 | 
			
		||||
                Handshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                Handshaked = this.OnDmtpActorHandshaked,
 | 
			
		||||
                Closed = OnDmtpActorClose,
 | 
			
		||||
                CreatedChannel = this.OnDmtpActorCreateChannel,
 | 
			
		||||
                Logger = this.Logger,
 | 
			
		||||
                Client = this,
 | 
			
		||||
                OnFindDmtpActor = this.m_findDmtpActor
 | 
			
		||||
                FindDmtpActor = this.m_findDmtpActor
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        private Task OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
            base.BreakOut(false, msg);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreateChannel(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
            return this.OnCreateChannel(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnHandshaked(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaking(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
            return this.OnHandshaking(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
@@ -350,6 +344,11 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        #region 事件触发
 | 
			
		||||
@@ -358,32 +357,53 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// 当创建通道
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        protected virtual async Task OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在完成握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 即将握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e">参数</param>
 | 
			
		||||
        protected virtual void OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当需要转发路由包时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        protected virtual async Task OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 事件触发
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private Func<string, Task<IDmtpActor>> m_findDmtpActor;
 | 
			
		||||
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
@@ -62,23 +62,34 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnConnected(TClient socketClient, ConnectedEventArgs e)
 | 
			
		||||
        protected override async Task OnConnected(TClient socketClient, ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            socketClient.m_internalOnRpcActorInit = this.PrivateOnRpcActorInit;
 | 
			
		||||
            base.OnConnected(socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IDmtpActor OnServiceFindDmtpActor(string id)
 | 
			
		||||
        {
 | 
			
		||||
            return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null;
 | 
			
		||||
            await base.OnConnected(socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private DmtpActor PrivateOnRpcActorInit()
 | 
			
		||||
        {
 | 
			
		||||
            return new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null
 | 
			
		||||
                FindDmtpActor = this.FindDmtpActor
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task<IDmtpActor> FindDmtpActor(string id)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.m_findDmtpActor != null)
 | 
			
		||||
                {
 | 
			
		||||
                    return await this.m_findDmtpActor.Invoke(id);
 | 
			
		||||
                }
 | 
			
		||||
                return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,14 +31,14 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
    public class HttpDmtpSocketClient : HttpSocketClient, IHttpDmtpSocketClient
 | 
			
		||||
    {
 | 
			
		||||
        internal Func<DmtpActor> m_internalOnRpcActorInit;
 | 
			
		||||
        private DmtpActor m_smtpActor;
 | 
			
		||||
        private DmtpActor m_dmtpActor;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_dmtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证超时时间,默认为3000ms
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -49,89 +49,72 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty);
 | 
			
		||||
 | 
			
		||||
        #region 断开
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_smtpActor == null)
 | 
			
		||||
            if (this.m_dmtpActor != null)
 | 
			
		||||
            {
 | 
			
		||||
                base.Close(msg);
 | 
			
		||||
                return;
 | 
			
		||||
                this.m_dmtpActor.SendClose(msg);
 | 
			
		||||
                this.m_dmtpActor.Close(msg);
 | 
			
		||||
            }
 | 
			
		||||
            this.m_smtpActor.Close(true, msg);
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region ResetId
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.ResetId(string)"/>
 | 
			
		||||
        public override void ResetId(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_smtpActor == null)
 | 
			
		||||
            {
 | 
			
		||||
                base.ResetId(newId);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.m_smtpActor.ResetId(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/>
 | 
			
		||||
        public async Task ResetIdAsync(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_smtpActor == null)
 | 
			
		||||
            {
 | 
			
		||||
                base.ResetId(newId);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.m_smtpActor.ResetIdAsync(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion ResetId
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="disposing"></param>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor?.SafeDispose();
 | 
			
		||||
            this.m_dmtpActor?.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message)
 | 
			
		||||
            {
 | 
			
		||||
                if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.PluginsManager.Enable)
 | 
			
		||||
                    {
 | 
			
		||||
                        this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return base.HandleReceivedData(byteBlock, requestInfo);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor?.Close(false, e.Message);
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
            this.m_dmtpActor?.Close(e.Message);
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 断开
 | 
			
		||||
 | 
			
		||||
        #region ResetId
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.ResetId(string)"/>
 | 
			
		||||
        public override void ResetId(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_dmtpActor == null)
 | 
			
		||||
            {
 | 
			
		||||
                base.ResetId(newId);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.m_dmtpActor.ResetId(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/>
 | 
			
		||||
        public async Task ResetIdAsync(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_dmtpActor == null)
 | 
			
		||||
            {
 | 
			
		||||
                base.ResetId(newId);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.m_dmtpActor.ResetIdAsync(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion ResetId
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="request"></param>
 | 
			
		||||
        protected override void OnReceivedHttpRequest(HttpRequest request)
 | 
			
		||||
        protected override async Task OnReceivedHttpRequest(HttpRequest request)
 | 
			
		||||
        {
 | 
			
		||||
            if (request.IsMethod(DmtpUtility.Dmtp) && request.IsUpgrade() &&
 | 
			
		||||
                string.Equals(request.Headers.Get(HttpHeaders.Upgrade), DmtpUtility.Dmtp, StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
@@ -142,69 +125,76 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                this.DefaultSend(new HttpResponse().SetStatus(101, "Switching Protocols").BuildAsBytes());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            base.OnReceivedHttpRequest(request);
 | 
			
		||||
            await base.OnReceivedHttpRequest(request);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message)
 | 
			
		||||
            {
 | 
			
		||||
                if (!await this.m_dmtpActor.InputReceivedData(message))
 | 
			
		||||
                {
 | 
			
		||||
                    await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpIdChanged(DmtpActor actor, IdChangedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(e.NewId);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SetRpcActor(DmtpActor actor)
 | 
			
		||||
        {
 | 
			
		||||
            actor.Id = this.Id;
 | 
			
		||||
            actor.OnResetId = this.ThisOnResetId;
 | 
			
		||||
            actor.IdChanged = this.OnDmtpIdChanged;
 | 
			
		||||
            actor.OutputSendAsync = this.ThisDmtpActorOutputSendAsync;
 | 
			
		||||
            actor.OutputSend = this.ThisDmtpActorOutputSend;
 | 
			
		||||
            actor.Client = this;
 | 
			
		||||
            actor.OnClose = this.OnDmtpActorClose;
 | 
			
		||||
            actor.OnRouting = this.OnDmtpActorRouting;
 | 
			
		||||
            actor.OnHandshaked = this.OnDmtpActorHandshaked;
 | 
			
		||||
            actor.OnHandshaking = this.OnDmtpActorHandshaking;
 | 
			
		||||
            actor.OnCreateChannel = this.OnDmtpActorCreateChannel;
 | 
			
		||||
            actor.Closed = this.OnDmtpActorClose;
 | 
			
		||||
            actor.Routing = this.OnDmtpActorRouting;
 | 
			
		||||
            actor.Handshaked = this.OnDmtpActorHandshaked;
 | 
			
		||||
            actor.Handshaking = this.OnDmtpActorHandshaking;
 | 
			
		||||
            actor.CreatedChannel = this.OnDmtpActorCreatedChannel;
 | 
			
		||||
            actor.Logger = this.Logger;
 | 
			
		||||
            this.m_smtpActor = actor;
 | 
			
		||||
            this.m_dmtpActor = actor;
 | 
			
		||||
 | 
			
		||||
            this.Protocol = DmtpUtility.DmtpProtocol;
 | 
			
		||||
            this.SetDataHandlingAdapter(new TcpDmtpAdapter());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisOnResetId(DmtpActor actor, WaitSetId waitSetId)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(waitSetId.NewId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task ThisDmtpActorOutputSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        private Task OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
            base.BreakOut(false, msg);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorCreatedChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreateChannel(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
            return this.OnCreatedChannel(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnHandshaked(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Token == this.VerifyToken)
 | 
			
		||||
            {
 | 
			
		||||
@@ -215,25 +205,12 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                e.Message = "Token不受理";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.OnHandshaking(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
            return this.OnHandshaking(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
@@ -244,32 +221,53 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// 当创建通道
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        protected virtual async Task OnCreatedChannel(CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在完成握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在验证Token时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e">参数</param>
 | 
			
		||||
        protected virtual void OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在需要转发路由包时。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        protected virtual async Task OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 事件
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,10 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Http;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -38,22 +38,25 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.Protocol = DmtpUtility.DmtpProtocol;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_dmtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.Id"/>
 | 
			
		||||
        public string Id => this.DmtpActor.Id;
 | 
			
		||||
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private SealedDmtpActor m_smtpActor;
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private SealedDmtpActor m_dmtpActor;
 | 
			
		||||
        private Func<string, Task<IDmtpActor>> m_findDmtpActor;
 | 
			
		||||
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
        #region 断开
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
@@ -62,10 +65,27 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.Close(true, msg);
 | 
			
		||||
            this.m_dmtpActor?.SendClose(msg);
 | 
			
		||||
            this.m_dmtpActor?.Close(msg);
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_dmtpActor?.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_dmtpActor?.Close(e.Message);
 | 
			
		||||
            await base.OnDisconnected(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 断开
 | 
			
		||||
 | 
			
		||||
        #region 连接
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -86,7 +106,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                    base.Connect(timeout);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
@@ -106,7 +126,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                    base.Connect(timeout);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token);
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
@@ -128,11 +148,10 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                }
 | 
			
		||||
                if (!this.Online)
 | 
			
		||||
                {
 | 
			
		||||
                    await base.ConnectAsync(timeout);
 | 
			
		||||
                    await base.ConnectAsync(timeout).ConfigureFalseAwait();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
 | 
			
		||||
                await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None).ConfigureFalseAwait();
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
@@ -153,11 +172,10 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                }
 | 
			
		||||
                if (!this.Online)
 | 
			
		||||
                {
 | 
			
		||||
                    await base.ConnectAsync(timeout);
 | 
			
		||||
                    await base.ConnectAsync(timeout).ConfigureFalseAwait();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token);
 | 
			
		||||
                await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token).ConfigureFalseAwait();
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
@@ -173,13 +191,13 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetId(string)"/>
 | 
			
		||||
        public void ResetId(string id)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.ResetId(id);
 | 
			
		||||
            this.m_dmtpActor.ResetId(id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/>
 | 
			
		||||
        public Task ResetIdAsync(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            return this.m_smtpActor.ResetIdAsync(newId);
 | 
			
		||||
            return this.m_dmtpActor.ResetIdAsync(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion ResetId
 | 
			
		||||
@@ -228,27 +246,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #endregion 发送
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            var message = (DmtpMessage)requestInfo;
 | 
			
		||||
            if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
            {
 | 
			
		||||
                if (this.PluginsManager.Enable)
 | 
			
		||||
                {
 | 
			
		||||
                    this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void LoadConfig(TouchSocketConfig config)
 | 
			
		||||
        {
 | 
			
		||||
@@ -259,82 +256,71 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                this.m_allowRoute = true;
 | 
			
		||||
                this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor;
 | 
			
		||||
            }
 | 
			
		||||
            this.m_smtpActor = new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            this.m_dmtpActor = new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                OutputSend = this.DmtpActorSend,
 | 
			
		||||
                OnRouting = this.OnDmtpActorRouting,
 | 
			
		||||
                OnHandshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                OnHandshaked = this.OnDmtpActorHandshaked,
 | 
			
		||||
                OnClose = this.OnDmtpActorClose,
 | 
			
		||||
                OutputSendAsync = this.DmtpActorSendAsync,
 | 
			
		||||
                Routing = this.OnDmtpActorRouting,
 | 
			
		||||
                Handshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                Handshaked = this.OnDmtpActorHandshaked,
 | 
			
		||||
                Closed = this.OnDmtpActorClose,
 | 
			
		||||
                Logger = this.Logger,
 | 
			
		||||
                Client = this,
 | 
			
		||||
                OnFindDmtpActor = this.m_findDmtpActor,
 | 
			
		||||
                OnCreateChannel = this.OnDmtpActorCreateChannel
 | 
			
		||||
                FindDmtpActor = this.m_findDmtpActor,
 | 
			
		||||
                CreatedChannel = this.OnDmtpActorCreateChannel
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
            this.DmtpActor.Close(false, e.Message);
 | 
			
		||||
            var message = (DmtpMessage)e.RequestInfo;
 | 
			
		||||
            if (!await this.m_dmtpActor.InputReceivedData(message).ConfigureFalseAwait())
 | 
			
		||||
            {
 | 
			
		||||
                await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await base.ReceivedData(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreateChannel(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaking(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            this.BreakOut(false, msg);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return this.OnCreatedChannel(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return this.OnHandshaked(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return this.OnHandshaking(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        #region 事件触发
 | 
			
		||||
@@ -343,32 +329,53 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// 当创建通道
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        protected virtual async Task OnCreatedChannel(CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在完成握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 即将握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e">参数</param>
 | 
			
		||||
        protected virtual void OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当需要转发路由包时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        protected virtual async Task OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 事件触发
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private Func<string, Task<IDmtpActor>> m_findDmtpActor;
 | 
			
		||||
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
@@ -68,19 +68,30 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override void OnConnecting(TClient socketClient, ConnectingEventArgs e)
 | 
			
		||||
        protected override async Task OnConnecting(TClient socketClient, ConnectingEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                Id = e.Id,
 | 
			
		||||
                OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null
 | 
			
		||||
                FindDmtpActor = this.FindDmtpActor
 | 
			
		||||
            });
 | 
			
		||||
            base.OnConnecting(socketClient, e);
 | 
			
		||||
            await base.OnConnecting(socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IDmtpActor OnServiceFindDmtpActor(string id)
 | 
			
		||||
        private async Task<IDmtpActor> FindDmtpActor(string id)
 | 
			
		||||
        {
 | 
			
		||||
            return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null;
 | 
			
		||||
            if (this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.m_findDmtpActor != null)
 | 
			
		||||
                {
 | 
			
		||||
                    return await this.m_findDmtpActor.Invoke(id);
 | 
			
		||||
                }
 | 
			
		||||
                return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -30,7 +30,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public partial class TcpDmtpSocketClient : SocketClient, ITcpDmtpSocketClient
 | 
			
		||||
    {
 | 
			
		||||
        private DmtpActor m_smtpActor;
 | 
			
		||||
        private DmtpActor m_dmtpActor;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// TcpDmtpSocketClient
 | 
			
		||||
@@ -40,12 +40,12 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.Protocol = DmtpUtility.DmtpProtocol;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_dmtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证超时时间,默认为3000ms
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -58,36 +58,23 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #region 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        private Task OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
            base.BreakOut(false, msg);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreateChannel(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
            return this.OnCreateChannel(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnHandshaked(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private async Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Token == this.VerifyToken)
 | 
			
		||||
            {
 | 
			
		||||
@@ -98,25 +85,12 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                e.Message = "Token不受理";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.OnHandshaking(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
            await this.OnHandshaking(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
@@ -127,102 +101,138 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// 当创建通道
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        protected virtual async Task OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在完成握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在验证Token时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e">参数</param>
 | 
			
		||||
        protected virtual void OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在需要转发路由包时。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        protected virtual async Task OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 事件
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        #region 断开
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="msg"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.Close(true, msg);
 | 
			
		||||
            this.m_dmtpActor?.SendClose(msg);
 | 
			
		||||
            this.m_dmtpActor?.Close(msg);
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_dmtpActor?.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_dmtpActor?.Close(e.Message);
 | 
			
		||||
            await base.OnDisconnected(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 断开
 | 
			
		||||
 | 
			
		||||
        #region ResetId
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetId(string)"/>
 | 
			
		||||
        public override void ResetId(string id)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.ResetId(id);
 | 
			
		||||
            this.m_dmtpActor.ResetId(id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/>
 | 
			
		||||
        public Task ResetIdAsync(string newId)
 | 
			
		||||
        {
 | 
			
		||||
            return this.m_smtpActor.ResetIdAsync(newId);
 | 
			
		||||
            return this.m_dmtpActor.ResetIdAsync(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion ResetId
 | 
			
		||||
 | 
			
		||||
        internal void SetDmtpActor(DmtpActor actor)
 | 
			
		||||
        {
 | 
			
		||||
            actor.OnResetId = this.ThisOnResetId;
 | 
			
		||||
            actor.IdChanged = this.ThisOnResetId;
 | 
			
		||||
            actor.OutputSend = this.ThisDmtpActorOutputSend;
 | 
			
		||||
            actor.OutputSendAsync = this.ThisDmtpActorOutputSendAsync;
 | 
			
		||||
            actor.Client = this;
 | 
			
		||||
            actor.OnClose = this.OnDmtpActorClose;
 | 
			
		||||
            actor.OnRouting = this.OnDmtpActorRouting;
 | 
			
		||||
            actor.OnHandshaked = this.OnDmtpActorHandshaked;
 | 
			
		||||
            actor.OnHandshaking = this.OnDmtpActorHandshaking;
 | 
			
		||||
            actor.OnCreateChannel = this.OnDmtpActorCreateChannel;
 | 
			
		||||
            actor.Closed = this.OnDmtpActorClose;
 | 
			
		||||
            actor.Routing = this.OnDmtpActorRouting;
 | 
			
		||||
            actor.Handshaked = this.OnDmtpActorHandshaked;
 | 
			
		||||
            actor.Handshaking = this.OnDmtpActorHandshaking;
 | 
			
		||||
            actor.CreatedChannel = this.OnDmtpActorCreateChannel;
 | 
			
		||||
            actor.Logger = this.Logger;
 | 
			
		||||
            this.m_smtpActor = actor;
 | 
			
		||||
            this.m_dmtpActor = actor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            var message = (DmtpMessage)requestInfo;
 | 
			
		||||
            if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
            var message = (DmtpMessage)e.RequestInfo;
 | 
			
		||||
            if (!await this.m_dmtpActor.InputReceivedData(message).ConfigureFalseAwait())
 | 
			
		||||
            {
 | 
			
		||||
                if (this.PluginsManager.Enable)
 | 
			
		||||
                {
 | 
			
		||||
                    this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                }
 | 
			
		||||
                await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
            await base.ReceivedData(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnConnected(ConnectedEventArgs e)
 | 
			
		||||
        protected override async Task OnConnected(ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.Id = this.Id;
 | 
			
		||||
            base.OnConnected(e);
 | 
			
		||||
            this.m_dmtpActor.Id = this.Id;
 | 
			
		||||
            await base.OnConnected(e).ConfigureFalseAwait();
 | 
			
		||||
 | 
			
		||||
            Task.Run(async () =>
 | 
			
		||||
            _ = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(this.VerifyTimeout);
 | 
			
		||||
                await Task.Delay(this.VerifyTimeout).ConfigureFalseAwait();
 | 
			
		||||
                if (!this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    this.TryShutdown();
 | 
			
		||||
@@ -231,23 +241,22 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.Close(false, e.Message);
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(waitSetId.NewId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task ThisDmtpActorOutputSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task ThisOnResetId(DmtpActor rpcActor, IdChangedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(e.NewId);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 发送
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -75,20 +75,20 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        protected override async Task ReceivedData(UdpReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var client = this.PrivateGetUdpDmtpClient(remoteEndPoint);
 | 
			
		||||
            var client = this.PrivateGetUdpDmtpClient(e.EndPoint);
 | 
			
		||||
            if (client == null)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var message = DmtpMessage.CreateFrom(byteBlock);
 | 
			
		||||
            if (!client.InputReceivedData(message))
 | 
			
		||||
            var message = DmtpMessage.CreateFrom(e.ByteBlock);
 | 
			
		||||
            if (!await client.InputReceivedData(message))
 | 
			
		||||
            {
 | 
			
		||||
                if (this.PluginsManager.Enable)
 | 
			
		||||
                {
 | 
			
		||||
                    this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), client, new DmtpMessageEventArgs(message));
 | 
			
		||||
                    await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), client, new DmtpMessageEventArgs(message));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,11 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
using ThingsGateway.Foundation.Sockets;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
{
 | 
			
		||||
@@ -45,16 +49,17 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        {
 | 
			
		||||
            this.Id = endPoint.ToString();
 | 
			
		||||
            this.OutputSend = this.RpcActorSend;
 | 
			
		||||
            this.OnCreateChannel = this.OnDmtpActorCreateChannel;
 | 
			
		||||
            this.OutputSendAsync = this.RpcActorSendAsync;
 | 
			
		||||
            this.CreatedChannel = this.OnDmtpActorCreatedChannel;
 | 
			
		||||
            this.m_udpSession = udpSession;
 | 
			
		||||
            this.m_endPoint = endPoint;
 | 
			
		||||
            this.Logger = logger;
 | 
			
		||||
            this.Client = this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorCreatedChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.pluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
            return this.pluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Created(IPluginsManager pluginsManager)
 | 
			
		||||
@@ -117,5 +122,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        {
 | 
			
		||||
            this.m_udpSession.Send(this.m_endPoint, transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task RpcActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return this.m_udpSession.SendAsync(this.m_endPoint, transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,7 +22,12 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System;
 | 
			
		||||
using System.Net.WebSockets;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
using ThingsGateway.Foundation.Sockets;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
@@ -49,16 +54,18 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 字段
 | 
			
		||||
#pragma warning disable CS0414
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
#pragma warning restore CS0414
 | 
			
		||||
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphoreForConnect = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphoreForSend = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private ClientWebSocket m_client;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private ValueCounter m_receiveCounter;
 | 
			
		||||
        private ValueCounter m_sendCounter;
 | 
			
		||||
        private SealedDmtpActor m_dmtpActor;
 | 
			
		||||
        private TcpDmtpAdapter m_smtpAdapter;
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private Func<string, Task<IDmtpActor>> m_findDmtpActor;
 | 
			
		||||
        private int m_receiveBufferSize = 1024 * 10;
 | 
			
		||||
        private ValueCounter m_receiveCounter;
 | 
			
		||||
        private int m_sendBufferSize = 1024 * 10;
 | 
			
		||||
        private ValueCounter m_sendCounter;
 | 
			
		||||
        private TcpDmtpAdapter m_dmtpAdapter;
 | 
			
		||||
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
@@ -92,25 +99,21 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public DateTime LastSendTime => this.m_sendCounter.LastIncrement;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 未实现
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<ByteBlock, bool> OnHandleRawBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 未实现
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IPluginsManager PluginsManager { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Protocol Protocol { get; set; } = DmtpUtility.DmtpProtocol;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override int ReceiveBufferSize => this.m_receiveBufferSize;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IPHost RemoteIPHost { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override int SendBufferSize => this.m_sendBufferSize;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -118,56 +121,15 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.Close(true, msg);
 | 
			
		||||
            this.m_dmtpActor.SendClose(msg);
 | 
			
		||||
            this.m_dmtpActor.Close(msg);
 | 
			
		||||
            this.PrivateClose(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public async Task ConnectAsync(int timeout = 5000)
 | 
			
		||||
        public Task ConnectAsync(int timeout = 5000)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.m_semaphore.WaitAsync();
 | 
			
		||||
                if (this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (this.m_client == null || this.m_client.State != WebSocketState.Open)
 | 
			
		||||
                {
 | 
			
		||||
                    this.m_client.SafeDispose();
 | 
			
		||||
                    this.m_client = new ClientWebSocket();
 | 
			
		||||
                    await this.m_client.ConnectAsync(this.RemoteIPHost, default);
 | 
			
		||||
 | 
			
		||||
                    this.m_dmtpActor = new SealedDmtpActor(false)
 | 
			
		||||
                    {
 | 
			
		||||
                        OutputSend = this.OnDmtpActorSend,
 | 
			
		||||
                        OnRouting = this.OnDmtpActorRouting,
 | 
			
		||||
                        OnHandshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                        OnHandshaked = this.OnDmtpActorHandshaked,
 | 
			
		||||
                        OnClose = this.OnDmtpActorClose,
 | 
			
		||||
                        Logger = this.Logger,
 | 
			
		||||
                        Client = this,
 | 
			
		||||
                        OnFindDmtpActor = this.m_findDmtpActor,
 | 
			
		||||
                        OnCreateChannel = this.OnDmtpActorCreateChannel
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    this.m_smtpAdapter = new TcpDmtpAdapter()
 | 
			
		||||
                    {
 | 
			
		||||
                        ReceivedCallBack = this.PrivateHandleReceivedData
 | 
			
		||||
                    };
 | 
			
		||||
                    _ = this.BeginReceive();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
                    this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty),
 | 
			
		||||
                    timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None);
 | 
			
		||||
                this.IsHandshaked = true;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.m_semaphore.Release();
 | 
			
		||||
            }
 | 
			
		||||
            return this.ConnectAsync(CancellationToken.None, timeout);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
@@ -175,7 +137,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.m_semaphore.WaitAsync();
 | 
			
		||||
                await this.m_semaphoreForConnect.WaitAsync();
 | 
			
		||||
                if (this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -190,17 +152,18 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                    this.m_dmtpActor = new SealedDmtpActor(false)
 | 
			
		||||
                    {
 | 
			
		||||
                        OutputSend = this.OnDmtpActorSend,
 | 
			
		||||
                        OnRouting = this.OnDmtpActorRouting,
 | 
			
		||||
                        OnHandshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                        OnHandshaked = this.OnDmtpActorHandshaked,
 | 
			
		||||
                        OnClose = this.OnDmtpActorClose,
 | 
			
		||||
                        OutputSendAsync = this.OnDmtpActorSendAsync,
 | 
			
		||||
                        Routing = this.OnDmtpActorRouting,
 | 
			
		||||
                        Handshaking = this.OnDmtpActorHandshaking,
 | 
			
		||||
                        Handshaked = this.OnDmtpActorHandshaked,
 | 
			
		||||
                        Closed = this.OnDmtpActorClose,
 | 
			
		||||
                        Logger = this.Logger,
 | 
			
		||||
                        Client = this,
 | 
			
		||||
                        OnFindDmtpActor = this.m_findDmtpActor,
 | 
			
		||||
                        OnCreateChannel = this.OnDmtpActorCreateChannel
 | 
			
		||||
                    };
 | 
			
		||||
                        FindDmtpActor = this.m_findDmtpActor,
 | 
			
		||||
                        CreatedChannel = this.OnDmtpActorCreateChannel
 | 
			
		||||
                    }; ;
 | 
			
		||||
 | 
			
		||||
                    this.m_smtpAdapter = new TcpDmtpAdapter()
 | 
			
		||||
                    this.m_dmtpAdapter = new TcpDmtpAdapter()
 | 
			
		||||
                    {
 | 
			
		||||
                        ReceivedCallBack = this.PrivateHandleReceivedData
 | 
			
		||||
                    };
 | 
			
		||||
@@ -214,7 +177,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.m_semaphore.Release();
 | 
			
		||||
                this.m_semaphoreForConnect.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -236,18 +199,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.DmtpActor.ResetId(newId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="ipHost"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public IWebSocketDmtpClient Setup(string ipHost)
 | 
			
		||||
        {
 | 
			
		||||
            var config = new TouchSocketConfig();
 | 
			
		||||
            config.SetRemoteIPHost(new IPHost(ipHost));
 | 
			
		||||
            return this.Setup(config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -297,7 +248,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
            if (this.Container.IsRegistered(typeof(IDmtpRouteService)))
 | 
			
		||||
            {
 | 
			
		||||
                this.m_allowRoute = true;
 | 
			
		||||
                this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -331,7 +281,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                        byteBlock.SetLength(result.Count);
 | 
			
		||||
                        this.m_receiveCounter.Increment(result.Count);
 | 
			
		||||
 | 
			
		||||
                        this.m_smtpAdapter.ReceivedInput(byteBlock);
 | 
			
		||||
                        this.m_dmtpAdapter.ReceivedInput(byteBlock);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@@ -353,7 +303,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                    this.m_client.CloseAsync(WebSocketCloseStatus.NormalClosure, msg, CancellationToken.None);
 | 
			
		||||
                    this.m_client.SafeDispose();
 | 
			
		||||
                    this.DmtpActor.SafeDispose();
 | 
			
		||||
                    this.m_smtpAdapter.SafeDispose();
 | 
			
		||||
                    this.m_dmtpAdapter.SafeDispose();
 | 
			
		||||
                    this.OnDisconnected(new DisconnectEventArgs(manual, msg));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -403,12 +353,12 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        private void OnReceivePeriod(long value)
 | 
			
		||||
        {
 | 
			
		||||
            this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value);
 | 
			
		||||
            this.m_receiveBufferSize = TouchSocketUtility.HitBufferLength(value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnSendPeriod(long value)
 | 
			
		||||
        {
 | 
			
		||||
            this.SendBufferSize = TouchSocketUtility.HitBufferLength(value);
 | 
			
		||||
            this.m_sendBufferSize = TouchSocketUtility.HitBufferLength(value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void PrivateClose(string msg)
 | 
			
		||||
@@ -419,82 +369,89 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            var message = (DmtpMessage)requestInfo;
 | 
			
		||||
            if (!this.m_dmtpActor.InputReceivedData(message))
 | 
			
		||||
            if (!this.m_dmtpActor.InputReceivedData(message).GetFalseAwaitResult())
 | 
			
		||||
            {
 | 
			
		||||
                if (this.PluginsManager.Enable)
 | 
			
		||||
                {
 | 
			
		||||
                    this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                }
 | 
			
		||||
                this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string arg2)
 | 
			
		||||
        private Task OnDmtpActorClose(DmtpActor actor, string arg2)
 | 
			
		||||
        {
 | 
			
		||||
            this.PrivateClose(arg2);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreateChannel(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
            return this.OnCreateChannel(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnHandshaked(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaking(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
            return this.OnHandshaking(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
            return this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            for (var i = 0; i < transferBytes.Length; i++)
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Task task;
 | 
			
		||||
                if (i == transferBytes.Length - 1)
 | 
			
		||||
                this.m_semaphoreForSend.Wait();
 | 
			
		||||
                for (var i = 0; i < transferBytes.Length; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, true, CancellationToken.None);
 | 
			
		||||
                    Task task;
 | 
			
		||||
                    if (i == transferBytes.Length - 1)
 | 
			
		||||
                    {
 | 
			
		||||
                        task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, true, CancellationToken.None);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, false, CancellationToken.None);
 | 
			
		||||
                    }
 | 
			
		||||
                    task.GetFalseAwaitResult();
 | 
			
		||||
                    this.m_sendCounter.Increment(transferBytes[i].Count);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    task = this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, false, CancellationToken.None);
 | 
			
		||||
                }
 | 
			
		||||
                task.ConfigureAwait(false);
 | 
			
		||||
                task.GetAwaiter().GetResult();
 | 
			
		||||
                this.m_sendCounter.Increment(transferBytes[i].Count);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.m_semaphoreForSend.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task OnDmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.m_semaphoreForSend.WaitAsync();
 | 
			
		||||
                for (var i = 0; i < transferBytes.Length; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i == transferBytes.Length - 1)
 | 
			
		||||
                    {
 | 
			
		||||
                        await this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, true, CancellationToken.None);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        await this.m_client.SendAsync(transferBytes[i], WebSocketMessageType.Binary, false, CancellationToken.None);
 | 
			
		||||
                    }
 | 
			
		||||
                    this.m_sendCounter.Increment(transferBytes[i].Count);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.m_semaphoreForSend.Release();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
@@ -505,34 +462,78 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// 当创建通道
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        protected virtual async Task OnCreateChannel(CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在完成握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaked(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 即将握手连接时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e">参数</param>
 | 
			
		||||
        protected virtual void OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        protected virtual async Task OnHandshaking(DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当需要转发路由包时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual void OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        protected virtual async Task OnRouting(PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 事件触发
 | 
			
		||||
 | 
			
		||||
        #region Receiver
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 不支持该功能
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="NotSupportedException"></exception>
 | 
			
		||||
        public void ClearReceiver()
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("不支持该功能");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 不支持该功能
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        /// <exception cref="NotSupportedException"></exception>
 | 
			
		||||
        public IReceiver CreateReceiver()
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("不支持该功能");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion Receiver
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,9 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,9 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
using ThingsGateway.Foundation.Sockets;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,11 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
using ThingsGateway.Foundation.Resources;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
@@ -22,10 +27,10 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建一个<see cref="DmtpFileTransferActor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        public DmtpFileTransferActor(IDmtpActor smtpActor)
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        public DmtpFileTransferActor(IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor = smtpActor;
 | 
			
		||||
            this.DmtpActor = dmtpActor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 委托
 | 
			
		||||
@@ -61,12 +66,8 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理收到的消息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public bool InputReceivedData(DmtpMessage message)
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public async Task<bool> InputReceivedData(DmtpMessage message)
 | 
			
		||||
        {
 | 
			
		||||
            var byteBlock = message.BodyByteBlock;
 | 
			
		||||
            if (message.ProtocolFlags == this.m_pullFileResourceInfo_Request)
 | 
			
		||||
@@ -77,11 +78,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileResource.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (waitFileResource.Route && this.DmtpActor.AllowRoute)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryRoute(RouteType.PullFile, waitFileResource))
 | 
			
		||||
                        if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitFileResource)))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor))
 | 
			
		||||
                            if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor)
 | 
			
		||||
                            {
 | 
			
		||||
                                actor.Send(this.m_pullFileResourceInfo_Request, byteBlock);
 | 
			
		||||
                                await actor.SendAsync(this.m_pullFileResourceInfo_Request, byteBlock);
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
@@ -96,12 +97,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                        waitFileResource.SwitchId();
 | 
			
		||||
                        byteBlock.Reset();
 | 
			
		||||
                        waitFileResource.Package(byteBlock);
 | 
			
		||||
                        this.DmtpActor.Send(this.m_pullFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                        await this.DmtpActor.SendAsync(this.m_pullFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        waitFileResource.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource);
 | 
			
		||||
                        _ = this.RequestPullFileResourceInfo(waitFileResource);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -118,9 +119,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileResource.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFileResource.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pullFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pullFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -143,9 +144,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileSection.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFileSection.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pullFileSection_Request, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pullFileSection_Request, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
@@ -153,7 +154,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                            waitFileSection.SwitchId();
 | 
			
		||||
                            byteBlock.Reset();
 | 
			
		||||
                            waitFileSection.Package(byteBlock);
 | 
			
		||||
                            this.DmtpActor.Send(this.m_pullFileSection_Response, byteBlock);
 | 
			
		||||
                            await this.DmtpActor.SendAsync(this.m_pullFileSection_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -177,9 +178,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileSection.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFileSection.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pullFileSection_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pullFileSection_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -202,11 +203,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileResource.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (waitFileResource.Route && this.DmtpActor.AllowRoute)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryRoute(RouteType.PullFile, waitFileResource))
 | 
			
		||||
                        if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitFileResource)))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor))
 | 
			
		||||
                            if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor)
 | 
			
		||||
                            {
 | 
			
		||||
                                actor.Send(this.m_pushFileResourceInfo_Request, byteBlock);
 | 
			
		||||
                                await actor.SendAsync(this.m_pushFileResourceInfo_Request, byteBlock);
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
@@ -221,12 +222,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                        byteBlock.Reset();
 | 
			
		||||
                        waitFileResource.SwitchId();
 | 
			
		||||
                        waitFileResource.Package(byteBlock);
 | 
			
		||||
                        this.DmtpActor.Send(this.m_pushFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                        await this.DmtpActor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        waitFileResource.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.RequestPushFileResourceInfo, waitFileResource);
 | 
			
		||||
                        _ = this.RequestPushFileResourceInfo(waitFileResource);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -243,9 +244,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileResource.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFileResource.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFileResource.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pushFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -268,9 +269,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileSection.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFileSection.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pushFileSection_Request, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pushFileSection_Request, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
@@ -278,7 +279,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                            waitFileSection.SwitchId();
 | 
			
		||||
                            byteBlock.Reset();
 | 
			
		||||
                            waitFileSection.Package(byteBlock);
 | 
			
		||||
                            this.DmtpActor.Send(this.m_pushFileSection_Response, byteBlock);
 | 
			
		||||
                            await this.DmtpActor.SendAsync(this.m_pushFileSection_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -303,9 +304,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileSection.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFileSection.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFileSection.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pushFileSection_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pushFileSection_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -328,9 +329,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFinishedPackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFinishedPackage.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_finishedFileResourceInfo_Request, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_finishedFileResourceInfo_Request, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
@@ -338,13 +339,13 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                            waitFinishedPackage.SwitchId();
 | 
			
		||||
                            byteBlock.Reset();
 | 
			
		||||
                            waitFinishedPackage.Package(byteBlock);
 | 
			
		||||
                            this.DmtpActor.Send(this.m_finishedFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                            await this.DmtpActor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        waitFinishedPackage.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.RequestFinishedFileResourceInfo, waitFinishedPackage);
 | 
			
		||||
                        _ = this.RequestFinishedFileResourceInfo(waitFinishedPackage);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -361,9 +362,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFinishedPackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitFinishedPackage.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitFinishedPackage.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_finishedFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -386,11 +387,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitSmallFilePackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (waitSmallFilePackage.Route && this.DmtpActor.AllowRoute)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryRoute(RouteType.PullFile, waitSmallFilePackage))
 | 
			
		||||
                        if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitSmallFilePackage)))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor))
 | 
			
		||||
                            if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor)
 | 
			
		||||
                            {
 | 
			
		||||
                                actor.Send(this.m_pullSmallFile_Request, byteBlock);
 | 
			
		||||
                                await actor.SendAsync(this.m_pullSmallFile_Request, byteBlock);
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
@@ -405,12 +406,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                        byteBlock.Reset();
 | 
			
		||||
                        waitSmallFilePackage.SwitchId();
 | 
			
		||||
                        waitSmallFilePackage.Package(byteBlock);
 | 
			
		||||
                        this.DmtpActor.Send(this.m_pullSmallFile_Response, byteBlock);
 | 
			
		||||
                        await this.DmtpActor.SendAsync(this.m_pullSmallFile_Response, byteBlock);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        waitSmallFilePackage.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.RequestPullSmallFile, waitSmallFilePackage);
 | 
			
		||||
                        _ = this.RequestPullSmallFile(waitSmallFilePackage);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -427,9 +428,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitSmallFilePackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitSmallFilePackage.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pullSmallFile_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pullSmallFile_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -452,11 +453,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitSmallFilePackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (waitSmallFilePackage.Route && this.DmtpActor.AllowRoute)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryRoute(RouteType.PullFile, waitSmallFilePackage))
 | 
			
		||||
                        if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.PullFile, waitSmallFilePackage)))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor))
 | 
			
		||||
                            if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor)
 | 
			
		||||
                            {
 | 
			
		||||
                                actor.Send(this.m_pushSmallFile_Request, byteBlock);
 | 
			
		||||
                                await actor.SendAsync(this.m_pushSmallFile_Request, byteBlock);
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
@@ -472,12 +473,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                        byteBlock.Reset();
 | 
			
		||||
                        waitSmallFilePackage.SwitchId();
 | 
			
		||||
                        waitSmallFilePackage.Package(byteBlock);
 | 
			
		||||
                        this.DmtpActor.Send(this.m_pushSmallFile_Response, byteBlock);
 | 
			
		||||
                        await this.DmtpActor.SendAsync(this.m_pushSmallFile_Response, byteBlock);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        waitSmallFilePackage.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.RequestPushSmallFile, waitSmallFilePackage);
 | 
			
		||||
                        _ = this.RequestPushSmallFile(waitSmallFilePackage);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -495,9 +496,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && waitSmallFilePackage.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(waitSmallFilePackage.TargetId) is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_pushSmallFile_Response, byteBlock);
 | 
			
		||||
                            await actor.SendAsync(this.m_pushSmallFile_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -568,24 +569,20 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
            return this.FileController.GetFullPath(this.m_rootPath, path);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool TryFindDmtpFileTransferActor(string targetId, out DmtpFileTransferActor rpcActor)
 | 
			
		||||
        private async Task<DmtpFileTransferActor> TryFindDmtpFileTransferActor(string targetId)
 | 
			
		||||
        {
 | 
			
		||||
            if (targetId == this.DmtpActor.Id)
 | 
			
		||||
            {
 | 
			
		||||
                rpcActor = this;
 | 
			
		||||
                return true;
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.DmtpActor.TryFindDmtpActor(targetId, out var smtpActor))
 | 
			
		||||
            if (await this.DmtpActor.TryFindDmtpActor(targetId).ConfigureFalseAwait() is DmtpActor dmtpActor)
 | 
			
		||||
            {
 | 
			
		||||
                if (smtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor newActor)
 | 
			
		||||
                if (dmtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor newActor)
 | 
			
		||||
                {
 | 
			
		||||
                    rpcActor = newActor;
 | 
			
		||||
                    return true;
 | 
			
		||||
                    return newActor;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            rpcActor = default;
 | 
			
		||||
            return false;
 | 
			
		||||
            return default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Id传输
 | 
			
		||||
@@ -598,9 +595,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                return this.PrivateFinishedFileResourceInfo(targetId, fileResourceInfo, code, metadata, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.FinishedFileResourceInfo(fileResourceInfo, code, metadata, timeout, token);
 | 
			
		||||
                return actor.FinishedFileResourceInfo(fileResourceInfo, code, metadata, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -625,9 +622,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                return this.PrivatePullFileResourceInfo(targetId, path, metadata, fileSectionSize, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.PullFileResourceInfo(path, metadata, fileSectionSize, timeout, token);
 | 
			
		||||
                return actor.PullFileResourceInfo(path, metadata, fileSectionSize, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -652,9 +649,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                return this.PrivatePullFileSection(targetId, fileSection, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.PullFileSection(fileSection, timeout, token);
 | 
			
		||||
                return actor.PullFileSection(fileSection, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -679,9 +676,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                return this.PrivatePushFileResourceInfo(targetId, savePath, fileResourceLocator, metadata, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.PushFileResourceInfo(savePath, fileResourceLocator, metadata, timeout, token);
 | 
			
		||||
                return actor.PushFileResourceInfo(savePath, fileResourceLocator, metadata, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -715,9 +712,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                return this.PrivatePushFileSection(targetId, fileResourceLocator, fileSection, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.PushFileSection(fileResourceLocator, fileSection, timeout, token);
 | 
			
		||||
                return actor.PushFileSection(fileResourceLocator, fileSection, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -1261,7 +1258,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                {
 | 
			
		||||
                    waitFinishedPackage.SwitchId();
 | 
			
		||||
                    waitFinishedPackage.Package(byteBlock);
 | 
			
		||||
                    this.DmtpActor.Send(this.m_finishedFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                    await this.DmtpActor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var args = new FileTransferedEventArgs(transferType, waitFinishedPackage?.Metadata, resourceInfo?.FileInfo, waitFinishedPackage.Code == ResultCode.Canceled ? Result.Canceled : resultThis)
 | 
			
		||||
@@ -1332,7 +1329,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                {
 | 
			
		||||
                    waitFileResource.SwitchId();
 | 
			
		||||
                    waitFileResource.Package(byteBlock);
 | 
			
		||||
                    this.DmtpActor.Send(this.m_pullFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                    await this.DmtpActor.SendAsync(this.m_pullFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
@@ -1454,7 +1451,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                {
 | 
			
		||||
                    waitFileResource.SwitchId();
 | 
			
		||||
                    waitFileResource.Package(byteBlock);
 | 
			
		||||
                    this.DmtpActor.Send(this.m_pushFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                    await this.DmtpActor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
@@ -1507,7 +1504,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileSection.Message = ex.Message;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                waitFileSection.Value.Dispose();
 | 
			
		||||
                waitFileSection.Value.SafeDispose();
 | 
			
		||||
                waitFileSection.Value = default;
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
                {
 | 
			
		||||
@@ -1528,7 +1525,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public PullSmallFileResult PullSmallFile(string targetId, string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var actor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return actor.PullSmallFile(path, metadata, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
@@ -1565,9 +1562,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Result PushSmallFile(string targetId, string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpFileTransferActor(targetId).GetFalseAwaitResult() is DmtpFileTransferActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.PushSmallFile(savePath, fileInfo, metadata, timeout, token);
 | 
			
		||||
                return actor.PushSmallFile(savePath, fileInfo, metadata, timeout, token);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -1827,7 +1824,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                {
 | 
			
		||||
                    waitSmallFilePackage.SwitchId();
 | 
			
		||||
                    waitSmallFilePackage.Package(byteBlock);
 | 
			
		||||
                    this.DmtpActor.Send(this.m_pullSmallFile_Response, byteBlock);
 | 
			
		||||
                    await this.DmtpActor.SendAsync(this.m_pullSmallFile_Response, byteBlock);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var resultArgs = new FileTransferedEventArgs(
 | 
			
		||||
@@ -1891,7 +1888,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
                {
 | 
			
		||||
                    waitSmallFilePackage.Package(byteBlock);
 | 
			
		||||
                    this.DmtpActor.Send(this.m_pushSmallFile_Response, byteBlock);
 | 
			
		||||
                    await this.DmtpActor.SendAsync(this.m_pushSmallFile_Response, byteBlock);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var resultArgs = new FileTransferedEventArgs(
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,10 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,11 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -48,7 +49,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var smtpFileTransferActor = new DmtpFileTransferActor(client.DmtpActor)
 | 
			
		||||
            var dmtpFileTransferActor = new DmtpFileTransferActor(client.DmtpActor)
 | 
			
		||||
            {
 | 
			
		||||
                FileController = this.m_fileResourceController,
 | 
			
		||||
                OnFileTransfering = this.OnFileTransfering,
 | 
			
		||||
@@ -56,25 +57,25 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                RootPath = this.RootPath,
 | 
			
		||||
                MaxSmallFileLength = this.MaxSmallFileLength
 | 
			
		||||
            };
 | 
			
		||||
            smtpFileTransferActor.SetProtocolFlags(this.StartProtocol);
 | 
			
		||||
            client.DmtpActor.SetDmtpFileTransferActor(smtpFileTransferActor);
 | 
			
		||||
            dmtpFileTransferActor.SetProtocolFlags(this.StartProtocol);
 | 
			
		||||
            client.DmtpActor.SetDmtpFileTransferActor(dmtpFileTransferActor);
 | 
			
		||||
 | 
			
		||||
            return e.InvokeNext();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e)
 | 
			
		||||
        public async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (client.DmtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor smtpFileTransferActor)
 | 
			
		||||
            if (client.DmtpActor.GetDmtpFileTransferActor() is DmtpFileTransferActor dmtpFileTransferActor)
 | 
			
		||||
            {
 | 
			
		||||
                if (smtpFileTransferActor.InputReceivedData(e.DmtpMessage))
 | 
			
		||||
                if (await dmtpFileTransferActor.InputReceivedData(e.DmtpMessage))
 | 
			
		||||
                {
 | 
			
		||||
                    e.Handled = true;
 | 
			
		||||
                    return EasyTask.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return e.InvokeNext();
 | 
			
		||||
            await e.InvokeNext();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpFileTransferActor.MaxSmallFileLength"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -48,21 +48,21 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpFileTransferActor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static IDmtpFileTransferActor GetDmtpFileTransferActor(this IDmtpActor smtpActor)
 | 
			
		||||
        public static IDmtpFileTransferActor GetDmtpFileTransferActor(this IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            return smtpActor.GetValue(DmtpFileTransferActorProperty);
 | 
			
		||||
            return dmtpActor.GetValue(DmtpFileTransferActorProperty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 向<see cref="DmtpActor"/>中设置<see cref="DmtpFileTransferActor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        /// <param name="smtpRpcActor"></param>
 | 
			
		||||
        internal static void SetDmtpFileTransferActor(this IDmtpActor smtpActor, DmtpFileTransferActor smtpRpcActor)
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        /// <param name="dmtpRpcActor"></param>
 | 
			
		||||
        internal static void SetDmtpFileTransferActor(this IDmtpActor dmtpActor, DmtpFileTransferActor dmtpRpcActor)
 | 
			
		||||
        {
 | 
			
		||||
            smtpActor.SetValue(DmtpFileTransferActorProperty, smtpRpcActor);
 | 
			
		||||
            dmtpActor.SetValue(DmtpFileTransferActorProperty, dmtpRpcActor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user