mirror of
				https://gitee.com/ThingsGateway/ThingsGateway.git
				synced 2025-11-04 17:43:58 +08:00 
			
		
		
		
	Compare commits
	
		
			85 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7ba9ac7a5b | ||
| 
						 | 
					85b8f26e8e | ||
| 
						 | 
					594a0f1410 | ||
| 
						 | 
					d317d757d7 | ||
| 
						 | 
					fdf0ba6318 | ||
| 
						 | 
					15bf7de5fa | ||
| 
						 | 
					d3402b058e | ||
| 
						 | 
					e7dfdd4031 | ||
| 
						 | 
					b2dd7b6364 | ||
| 
						 | 
					9bd6d9abbf | ||
| 
						 | 
					cd14428fea | ||
| 
						 | 
					19d9f03c2b | ||
| 
						 | 
					0d57e72bbf | ||
| 
						 | 
					329516a61b | ||
| 
						 | 
					d566869589 | ||
| 
						 | 
					9cb8d8e6c7 | ||
| 
						 | 
					9de3c57e5d | ||
| 
						 | 
					f32ff92b0b | ||
| 
						 | 
					88d71e271e | ||
| 
						 | 
					fd9c14612a | ||
| 
						 | 
					e26e5a160f | ||
| 
						 | 
					b836bfed22 | ||
| 
						 | 
					a4b598c6d0 | ||
| 
						 | 
					c9ab755839 | ||
| 
						 | 
					9920edba53 | ||
| 
						 | 
					12bd7280d1 | ||
| 
						 | 
					d30ea7f63b | ||
| 
						 | 
					ebd3390db6 | ||
| 
						 | 
					9a374a9ebc | ||
| 
						 | 
					b1bc22cb08 | ||
| 
						 | 
					4930d53890 | ||
| 
						 | 
					c31327b5bc | ||
| 
						 | 
					3f2aa1f1e1 | ||
| 
						 | 
					6e78c00a96 | ||
| 
						 | 
					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 | 
@@ -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.10</Version>
 | 
			
		||||
		<Version>3.0.0.25</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));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,10 @@
 | 
			
		||||
        <MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@port />
 | 
			
		||||
 | 
			
		||||
        <MButton Class="ma-1" OnClick=@Connect Color="primary">
 | 
			
		||||
            连接
 | 
			
		||||
            启动
 | 
			
		||||
        </MButton>
 | 
			
		||||
        <MButton Class="ma-1" OnClick=@DisConnect Color="red">
 | 
			
		||||
            断开
 | 
			
		||||
            停止
 | 
			
		||||
        </MButton>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊȫ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
			
		||||
//  <EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>룩<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Diego<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
			
		||||
//  Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD>Ŀ<EFBFBD>ԴЭ<EFBFBD>鼰<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
 | 
			
		||||
//  GiteeԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQȺ<EFBFBD><EFBFBD>605534569
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
@@ -26,7 +26,7 @@ public partial class MainLayout
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "Href": "/index",
 | 
			
		||||
    "Title": "<EFBFBD><EFBFBD>ҳ"
 | 
			
		||||
    "Title": "首页"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Title": "Modbus",
 | 
			
		||||
 
 | 
			
		||||
@@ -56,10 +56,10 @@
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\MqttRpcNameVaueWithId.cs" Link="Pages\Mqtt\MqttRpcNameVaueWithId.cs" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor.cs" Link="Pages\Mqtt\MqttClientDebugPage.razor.cs" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor.cs" Link="Pages\Mqtt\MqttClientPage.razor.cs" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\PrivateLogger.cs" Link="Pages\Mqtt\PrivateLogger.cs" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClient.cs" Link="Pages\Mqtt\MqttRpcClient.cs" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.cs" />
 | 
			
		||||
		<Compile Include="..\..\Web\ThingsGateway.Gateway.Application\Workers\ManageGateway\MqttLoggerExtensions.cs" Link="Pages\Mqtt\MqttLoggerExtensions.cs" />
 | 
			
		||||
		<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor" Link="Pages\DLT645\DLT645_2007DebugPage.razor" />
 | 
			
		||||
		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor.cs" />
 | 
			
		||||
		<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor" />
 | 
			
		||||
@@ -115,20 +115,20 @@
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<ItemGroup >
 | 
			
		||||
		<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" />
 | 
			
		||||
	<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" />
 | 
			
		||||
		<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" />-->
 | 
			
		||||
		<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj" />
 | 
			
		||||
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	<ItemGroup >
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<Project>
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<Version>3.0.0.10</Version>
 | 
			
		||||
		<Version>3.0.0.25</Version>
 | 
			
		||||
		<GenerateDocumentationFile>True</GenerateDocumentationFile>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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/>
 | 
			
		||||
@@ -409,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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -186,7 +186,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                var item = commandResult.Content;
 | 
			
		||||
                if (FrameTime != 0)
 | 
			
		||||
                    Thread.Sleep(FrameTime);
 | 
			
		||||
                var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
                var WaitingClientEx = client.CreateWaitingClient(new() { });
 | 
			
		||||
                var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
 | 
			
		||||
                return (MessageBase)result.RequestInfo;
 | 
			
		||||
            }
 | 
			
		||||
@@ -213,7 +213,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
 | 
			
		||||
                var item = commandResult.Content;
 | 
			
		||||
                await Task.Delay(FrameTime, cancellationToken);
 | 
			
		||||
                var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
                var WaitingClientEx = client.CreateWaitingClient(new() { });
 | 
			
		||||
                var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
 | 
			
		||||
                return (MessageBase)result.RequestInfo;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -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/>
 | 
			
		||||
@@ -429,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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,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,4 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
@@ -13,6 +13,33 @@
 | 
			
		||||
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 +49,7 @@ public class OPCNodeAttribute
 | 
			
		||||
    /// 属性的名称
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Name { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 操作结果状态描述
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -31,10 +59,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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -36,11 +36,42 @@ internal partial class SiemensHelper
 | 
			
		||||
    //    return OperResult.CreateSuccessResult<byte[]>(numArray);
 | 
			
		||||
    //}
 | 
			
		||||
 | 
			
		||||
    internal static OperResult<byte[]> AnalysisReadByte(byte[] sends, byte[] content)
 | 
			
		||||
    internal static OperResult<byte[], FilterResult> AnalysisReadByte(byte[] sends, byte[] content)
 | 
			
		||||
    {
 | 
			
		||||
        int length = 0;
 | 
			
		||||
        int itemLen = (sends.Length - 19) / 12;
 | 
			
		||||
 | 
			
		||||
        //添加错误代码校验
 | 
			
		||||
        if (content[17] + content[18] > 0)
 | 
			
		||||
        {
 | 
			
		||||
            return new($"PLC返回错误,错误类型{content[17].ToString("X2")}错误代码:{content[18].ToString("X2")}")
 | 
			
		||||
            {
 | 
			
		||||
                Content2 = FilterResult.Success
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        if (content.Length < 21)
 | 
			
		||||
        {
 | 
			
		||||
            return new($"长度不足")
 | 
			
		||||
            {
 | 
			
		||||
                Content2 = FilterResult.Cache
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        if (content.Length < 25 + content[20])
 | 
			
		||||
        {
 | 
			
		||||
            return new($"长度不足")
 | 
			
		||||
            {
 | 
			
		||||
                Content2 = FilterResult.Cache
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        //添加返回代码校验
 | 
			
		||||
        if (content[21] != 0xff)
 | 
			
		||||
        {
 | 
			
		||||
            return new($"PLC返回错误,返回代码{content[21].ToString("X2")}")
 | 
			
		||||
            {
 | 
			
		||||
                Content2 = FilterResult.Success
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (int index = 0; index < itemLen; index++)
 | 
			
		||||
        {
 | 
			
		||||
            if (sends[22 + (index * 12)] >= (byte)S7WordLength.Word)
 | 
			
		||||
@@ -53,9 +84,9 @@ internal partial class SiemensHelper
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (content.Length < 21 || content[20] != itemLen)
 | 
			
		||||
        if (content[20] != itemLen)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>("数据块长度校验失败");
 | 
			
		||||
            return new("数据块长度校验失败");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        byte[] dataArray = new byte[length];
 | 
			
		||||
@@ -105,29 +136,39 @@ internal partial class SiemensHelper
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return new OperResult<byte[]>((int)content[index2] + GetCpuError(content[index2]));
 | 
			
		||||
                    return new((int)content[index2] + GetCpuError(content[index2]))
 | 
			
		||||
                    {
 | 
			
		||||
                        Content2 = FilterResult.Success
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return OperResult.CreateSuccessResult(dataArray);
 | 
			
		||||
        return OperResult.CreateSuccessResult(dataArray, FilterResult.Success);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal static OperResult<byte[]> AnalysisWrite(byte[] content)
 | 
			
		||||
    internal static OperResult<byte[], FilterResult> AnalysisWrite(byte[] content)
 | 
			
		||||
    {
 | 
			
		||||
        if (content.Length < 22)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>() { Message = "未知错误" };
 | 
			
		||||
            return new()
 | 
			
		||||
            {
 | 
			
		||||
                Message = "长度不足",
 | 
			
		||||
                Content2 = FilterResult.Success
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        byte err = content[21];
 | 
			
		||||
        if (err != byte.MaxValue)
 | 
			
		||||
        {
 | 
			
		||||
            return new OperResult<byte[]>((int)content[21] + GetCpuError(content[21]));
 | 
			
		||||
            return new($"错误代码:{(int)content[21]}描述:{GetCpuError(content[21])}")
 | 
			
		||||
            {
 | 
			
		||||
                Content2 = FilterResult.Success
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return OperResult.CreateSuccessResult(content);
 | 
			
		||||
            return OperResult.CreateSuccessResult(content, FilterResult.Success);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -123,34 +123,7 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
        #region 设置
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 远程TSAP,需重新连接
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int DestTSAP
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return
 | 
			
		||||
                    _currentPlc == SiemensEnum.S200 || _currentPlc == SiemensEnum.S200Smart ?
 | 
			
		||||
                    (ISO_CR[17] * 256) + ISO_CR[18] :
 | 
			
		||||
                    (ISO_CR[20] * 256) + ISO_CR[21];
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if (_currentPlc == SiemensEnum.S200 || _currentPlc == SiemensEnum.S200Smart)
 | 
			
		||||
                {
 | 
			
		||||
                    ISO_CR[17] = BitConverter.GetBytes(value)[1];
 | 
			
		||||
                    ISO_CR[18] = BitConverter.GetBytes(value)[0];
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    ISO_CR[20] = BitConverter.GetBytes(value)[1];
 | 
			
		||||
                    ISO_CR[21] = BitConverter.GetBytes(value)[0];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 本地TSAP,需重新连接
 | 
			
		||||
        /// 本地TSAP
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int LocalTSAP
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -35,10 +35,10 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override FilterResult UnpackResponse(SiemensMessage request, byte[] send, byte[] body, byte[] response)
 | 
			
		||||
    {
 | 
			
		||||
        var result = new OperResult<byte[]>();
 | 
			
		||||
        var result = new OperResult<byte[], FilterResult>();
 | 
			
		||||
        if (response[2] * 256 + response[3] == 7)
 | 
			
		||||
        {
 | 
			
		||||
            result = new OperResult<byte[]>() { Content = response };
 | 
			
		||||
            result = new() { Content = response, Content2 = FilterResult.Success };
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@@ -56,6 +56,6 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte
 | 
			
		||||
        request.ErrorCode = result.ErrorCode;
 | 
			
		||||
        request.Message = result.Message;
 | 
			
		||||
        request.Content = result.Content;
 | 
			
		||||
        return FilterResult.Success;
 | 
			
		||||
        return result.Content2;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
0x00       Reserved 未定义,预留
 | 
			
		||||
 | 
			
		||||
0x01       Hardware error   硬件错误
 | 
			
		||||
 | 
			
		||||
0x03       Accessing the object not allowed 对象不允许访问
 | 
			
		||||
 | 
			
		||||
0x05       Invalid address     无效地址,所需的地址超出此PLC的极限
 | 
			
		||||
 | 
			
		||||
0x06       Data type not supported     数据类型不支持
 | 
			
		||||
 | 
			
		||||
0x07       Data type inconsistent 日期类型不一致
 | 
			
		||||
 | 
			
		||||
0x0a       Object does not exist    对象不存在
 | 
			
		||||
 | 
			
		||||
0xff         Success  成功
 | 
			
		||||
@@ -0,0 +1,825 @@
 | 
			
		||||
附录一:错误码具体含义
 | 
			
		||||
 | 
			
		||||
0x0000
 | 
			
		||||
 | 
			
		||||
没有错误
 | 
			
		||||
 | 
			
		||||
0x0110
 | 
			
		||||
 | 
			
		||||
块号无效
 | 
			
		||||
 | 
			
		||||
0x0111
 | 
			
		||||
 | 
			
		||||
请求长度无效
 | 
			
		||||
 | 
			
		||||
0x0112
 | 
			
		||||
 | 
			
		||||
参数无效
 | 
			
		||||
 | 
			
		||||
0x0113
 | 
			
		||||
 | 
			
		||||
块类型无效
 | 
			
		||||
 | 
			
		||||
0x0114
 | 
			
		||||
 | 
			
		||||
找不到块
 | 
			
		||||
 | 
			
		||||
0x0115
 | 
			
		||||
 | 
			
		||||
块已存在
 | 
			
		||||
 | 
			
		||||
0x0116
 | 
			
		||||
 | 
			
		||||
块被写保护
 | 
			
		||||
 | 
			
		||||
0x0117
 | 
			
		||||
 | 
			
		||||
块/操作系统更新太大
 | 
			
		||||
 | 
			
		||||
0x0118
 | 
			
		||||
 | 
			
		||||
块号无效
 | 
			
		||||
 | 
			
		||||
0x0119
 | 
			
		||||
 | 
			
		||||
输入的密码不正确
 | 
			
		||||
 | 
			
		||||
0x011A
 | 
			
		||||
 | 
			
		||||
PG资源错误
 | 
			
		||||
 | 
			
		||||
0x011B
 | 
			
		||||
 | 
			
		||||
PLC资源错误
 | 
			
		||||
 | 
			
		||||
0x011C
 | 
			
		||||
 | 
			
		||||
协议错误
 | 
			
		||||
 | 
			
		||||
0x011D
 | 
			
		||||
 | 
			
		||||
块太多(与模块相关的限制)
 | 
			
		||||
 | 
			
		||||
0x011E
 | 
			
		||||
 | 
			
		||||
不再与数据库建立连接,或者S7DOS句柄无效
 | 
			
		||||
 | 
			
		||||
0x011F
 | 
			
		||||
 | 
			
		||||
结果缓冲区太小
 | 
			
		||||
 | 
			
		||||
0x0120
 | 
			
		||||
 | 
			
		||||
块结束列表
 | 
			
		||||
 | 
			
		||||
0x0140
 | 
			
		||||
 | 
			
		||||
可用内存不足
 | 
			
		||||
 | 
			
		||||
0x0141
 | 
			
		||||
 | 
			
		||||
由于缺少资源,无法处理作业
 | 
			
		||||
 | 
			
		||||
0x8001
 | 
			
		||||
 | 
			
		||||
当块处于当前状态时,无法执行请求的服务
 | 
			
		||||
 | 
			
		||||
0x8003
 | 
			
		||||
 | 
			
		||||
S7协议错误:传输块时发生错误
 | 
			
		||||
 | 
			
		||||
0x8100
 | 
			
		||||
 | 
			
		||||
应用程序,一般错误:远程模块未知的服务
 | 
			
		||||
 | 
			
		||||
0x8104
 | 
			
		||||
 | 
			
		||||
未在模块上实现此服务或报告了帧错误
 | 
			
		||||
 | 
			
		||||
0x8204
 | 
			
		||||
 | 
			
		||||
对象的类型规范不一致
 | 
			
		||||
 | 
			
		||||
0x8205
 | 
			
		||||
 | 
			
		||||
复制的块已存在且未链接
 | 
			
		||||
 | 
			
		||||
0x8301
 | 
			
		||||
 | 
			
		||||
模块上的内存空间或工作内存不足,或者指定的存储介质不可访问
 | 
			
		||||
 | 
			
		||||
0x8302
 | 
			
		||||
 | 
			
		||||
可用资源太少或处理器资源不可用
 | 
			
		||||
 | 
			
		||||
0x8304
 | 
			
		||||
 | 
			
		||||
无法进一步并行上传。存在资源瓶颈
 | 
			
		||||
 | 
			
		||||
0x8305
 | 
			
		||||
 | 
			
		||||
功能不可用
 | 
			
		||||
 | 
			
		||||
0x8306
 | 
			
		||||
 | 
			
		||||
工作内存不足(用于复制,链接,加载AWP)
 | 
			
		||||
 | 
			
		||||
0x8307
 | 
			
		||||
 | 
			
		||||
保持性工作记忆不够(用于复制,链接,加载AWP)
 | 
			
		||||
 | 
			
		||||
0x8401
 | 
			
		||||
 | 
			
		||||
S7协议错误:无效的服务序列(例如,加载或上载块)
 | 
			
		||||
 | 
			
		||||
0x8402
 | 
			
		||||
 | 
			
		||||
由于寻址对象的状态,服务无法执行
 | 
			
		||||
 | 
			
		||||
0x8404
 | 
			
		||||
 | 
			
		||||
S7协议:无法执行该功能
 | 
			
		||||
 | 
			
		||||
0x8405
 | 
			
		||||
 | 
			
		||||
远程块处于DISABLE状态(CFB)。该功能无法执行
 | 
			
		||||
 | 
			
		||||
0x8500
 | 
			
		||||
 | 
			
		||||
S7协议错误:帧错误
 | 
			
		||||
 | 
			
		||||
0x8503
 | 
			
		||||
 | 
			
		||||
来自模块的警报:服务过早取消
 | 
			
		||||
 | 
			
		||||
0x8701
 | 
			
		||||
 | 
			
		||||
寻址通信伙伴上的对象时出错(例如,区域长度错误)
 | 
			
		||||
 | 
			
		||||
0x8702
 | 
			
		||||
 | 
			
		||||
模块不支持所请求的服务
 | 
			
		||||
 | 
			
		||||
0x8703
 | 
			
		||||
 | 
			
		||||
拒绝访问对象
 | 
			
		||||
 | 
			
		||||
0x8704
 | 
			
		||||
 | 
			
		||||
访问错误:对象已损坏
 | 
			
		||||
 | 
			
		||||
0xD001
 | 
			
		||||
 | 
			
		||||
协议错误:非法的作业号
 | 
			
		||||
 | 
			
		||||
0xD002
 | 
			
		||||
 | 
			
		||||
参数错误:非法的作业变体
 | 
			
		||||
 | 
			
		||||
0xD003
 | 
			
		||||
 | 
			
		||||
参数错误:模块不支持调试功能
 | 
			
		||||
 | 
			
		||||
0xD004
 | 
			
		||||
 | 
			
		||||
参数错误:作业状态非法
 | 
			
		||||
 | 
			
		||||
0xD005
 | 
			
		||||
 | 
			
		||||
参数错误:作业终止非法
 | 
			
		||||
 | 
			
		||||
0xD006
 | 
			
		||||
 | 
			
		||||
参数错误:非法链路断开ID
 | 
			
		||||
 | 
			
		||||
0xD007
 | 
			
		||||
 | 
			
		||||
参数错误:缓冲区元素数量非法
 | 
			
		||||
 | 
			
		||||
0xD008
 | 
			
		||||
 | 
			
		||||
参数错误:扫描速率非法
 | 
			
		||||
 | 
			
		||||
0xD009
 | 
			
		||||
 | 
			
		||||
参数错误:执行次数非法
 | 
			
		||||
 | 
			
		||||
0xD00A
 | 
			
		||||
 | 
			
		||||
参数错误:非法触发事件
 | 
			
		||||
 | 
			
		||||
0xD00B
 | 
			
		||||
 | 
			
		||||
参数错误:非法触发条件
 | 
			
		||||
 | 
			
		||||
0xD011
 | 
			
		||||
 | 
			
		||||
调用环境路径中的参数错误:块不存在
 | 
			
		||||
 | 
			
		||||
0xD012
 | 
			
		||||
 | 
			
		||||
参数错误:块中的地址错误
 | 
			
		||||
 | 
			
		||||
0xD014
 | 
			
		||||
 | 
			
		||||
参数错误:正在删除/覆盖块
 | 
			
		||||
 | 
			
		||||
0xD015
 | 
			
		||||
 | 
			
		||||
参数错误:标签地址非法
 | 
			
		||||
 | 
			
		||||
0xD016
 | 
			
		||||
 | 
			
		||||
参数错误:由于用户程序错误,无法测试作业
 | 
			
		||||
 | 
			
		||||
0xD017
 | 
			
		||||
 | 
			
		||||
参数错误:非法触发号
 | 
			
		||||
 | 
			
		||||
0xD025
 | 
			
		||||
 | 
			
		||||
参数错误:路径无效
 | 
			
		||||
 | 
			
		||||
0xD026
 | 
			
		||||
 | 
			
		||||
参数错误:非法访问类型
 | 
			
		||||
 | 
			
		||||
0xD027
 | 
			
		||||
 | 
			
		||||
参数错误:不允许此数据块数
 | 
			
		||||
 | 
			
		||||
0xD031
 | 
			
		||||
 | 
			
		||||
内部协议错误
 | 
			
		||||
 | 
			
		||||
0xD032
 | 
			
		||||
 | 
			
		||||
参数错误:结果缓冲区长度错误
 | 
			
		||||
 | 
			
		||||
0xD033
 | 
			
		||||
 | 
			
		||||
协议错误:作业长度错误
 | 
			
		||||
 | 
			
		||||
0xD03F
 | 
			
		||||
 | 
			
		||||
编码错误:参数部分出错(例如,保留字节不等于0)
 | 
			
		||||
 | 
			
		||||
0xD041
 | 
			
		||||
 | 
			
		||||
数据错误:非法状态列表ID
 | 
			
		||||
 | 
			
		||||
0xD042
 | 
			
		||||
 | 
			
		||||
数据错误:标签地址非法
 | 
			
		||||
 | 
			
		||||
0xD043
 | 
			
		||||
 | 
			
		||||
数据错误:找不到引用的作业,检查作业数据
 | 
			
		||||
 | 
			
		||||
0xD044
 | 
			
		||||
 | 
			
		||||
数据错误:标签值非法,检查作业数据
 | 
			
		||||
 | 
			
		||||
0xD045
 | 
			
		||||
 | 
			
		||||
数据错误:HOLD中不允许退出ODIS控制
 | 
			
		||||
 | 
			
		||||
0xD046
 | 
			
		||||
 | 
			
		||||
数据错误:运行时测量期间非法测量阶段
 | 
			
		||||
 | 
			
		||||
0xD047
 | 
			
		||||
 | 
			
		||||
数据错误:“读取作业列表”中的非法层次结构
 | 
			
		||||
 | 
			
		||||
0xD048
 | 
			
		||||
 | 
			
		||||
数据错误:“删除作业”中的非法删除ID
 | 
			
		||||
 | 
			
		||||
0xD049
 | 
			
		||||
 | 
			
		||||
“替换作业”中的替换ID无效
 | 
			
		||||
 | 
			
		||||
0xD04A
 | 
			
		||||
 | 
			
		||||
执行'程序状态'时出错
 | 
			
		||||
 | 
			
		||||
0xD05F
 | 
			
		||||
 | 
			
		||||
编码错误:数据部分出错(例如,保留字节不等于0,...)
 | 
			
		||||
 | 
			
		||||
0xD061
 | 
			
		||||
 | 
			
		||||
资源错误:没有作业的内存空间
 | 
			
		||||
 | 
			
		||||
0xD062
 | 
			
		||||
 | 
			
		||||
资源错误:作业列表已满
 | 
			
		||||
 | 
			
		||||
0xD063
 | 
			
		||||
 | 
			
		||||
资源错误:触发事件占用
 | 
			
		||||
 | 
			
		||||
0xD064
 | 
			
		||||
 | 
			
		||||
资源错误:没有足够的内存空间用于一个结果缓冲区元素
 | 
			
		||||
 | 
			
		||||
0xD065
 | 
			
		||||
 | 
			
		||||
资源错误:没有足够的内存空间用于多个结果缓冲区元素
 | 
			
		||||
 | 
			
		||||
0xD066
 | 
			
		||||
 | 
			
		||||
资源错误:可用于运行时测量的计时器被另一个作业占用
 | 
			
		||||
 | 
			
		||||
0xD067
 | 
			
		||||
 | 
			
		||||
资源错误:“修改标记”作业过多(特别是多处理器操作)
 | 
			
		||||
 | 
			
		||||
0xD081
 | 
			
		||||
 | 
			
		||||
当前模式下不允许使用的功能
 | 
			
		||||
 | 
			
		||||
0xD082
 | 
			
		||||
 | 
			
		||||
模式错误:无法退出HOLD模式
 | 
			
		||||
 | 
			
		||||
0xD0A1
 | 
			
		||||
 | 
			
		||||
当前保护级别不允许使用的功能
 | 
			
		||||
 | 
			
		||||
0xD0A2
 | 
			
		||||
 | 
			
		||||
目前无法运行,因为正在运行的函数会修改内存
 | 
			
		||||
 | 
			
		||||
0xD0A3
 | 
			
		||||
 | 
			
		||||
I / O上活动的“修改标记”作业太多(特别是多处理器操作)
 | 
			
		||||
 | 
			
		||||
0xD0A4
 | 
			
		||||
 | 
			
		||||
'强制'已经建立
 | 
			
		||||
 | 
			
		||||
0xD0A5
 | 
			
		||||
 | 
			
		||||
找不到引用的作业
 | 
			
		||||
 | 
			
		||||
0xD0A6
 | 
			
		||||
 | 
			
		||||
无法禁用/启用作业
 | 
			
		||||
 | 
			
		||||
0xD0A7
 | 
			
		||||
 | 
			
		||||
无法删除作业,例如因为当前正在读取作业
 | 
			
		||||
 | 
			
		||||
0xD0A8
 | 
			
		||||
 | 
			
		||||
无法替换作业,例如因为当前正在读取或删除作业
 | 
			
		||||
 | 
			
		||||
0xD0A9
 | 
			
		||||
 | 
			
		||||
无法读取作业,例如因为当前正在删除作业
 | 
			
		||||
 | 
			
		||||
0xD0AA
 | 
			
		||||
 | 
			
		||||
处理操作超出时间限制
 | 
			
		||||
 | 
			
		||||
0xD0AB
 | 
			
		||||
 | 
			
		||||
进程操作中的作业参数无效
 | 
			
		||||
 | 
			
		||||
0xD0AC
 | 
			
		||||
 | 
			
		||||
进程操作中的作业数据无效
 | 
			
		||||
 | 
			
		||||
0xD0AD
 | 
			
		||||
 | 
			
		||||
已设置操作模式
 | 
			
		||||
 | 
			
		||||
0xD0AE
 | 
			
		||||
 | 
			
		||||
作业是通过不同的连接设置的,只能通过此连接进行处理
 | 
			
		||||
 | 
			
		||||
0xD0C1
 | 
			
		||||
 | 
			
		||||
访问标签时至少检测到一个错误
 | 
			
		||||
 | 
			
		||||
0xD0C2
 | 
			
		||||
 | 
			
		||||
切换到STOP / HOLD模式
 | 
			
		||||
 | 
			
		||||
0xD0C3
 | 
			
		||||
 | 
			
		||||
访问标记时至少检测到一个错误。模式更改为STOP / HOLD
 | 
			
		||||
 | 
			
		||||
0xD0C4
 | 
			
		||||
 | 
			
		||||
运行时测量期间超时
 | 
			
		||||
 | 
			
		||||
0xD0C5
 | 
			
		||||
 | 
			
		||||
块堆栈的显示不一致,因为块被删除/重新加载
 | 
			
		||||
 | 
			
		||||
0xD0C6
 | 
			
		||||
 | 
			
		||||
作业已被删除,因为它所引用的作业已被删除
 | 
			
		||||
 | 
			
		||||
0xD0C7
 | 
			
		||||
 | 
			
		||||
由于退出了STOP模式,因此作业被自动删除
 | 
			
		||||
 | 
			
		||||
0xD0C8
 | 
			
		||||
 | 
			
		||||
由于测试作业和正在运行的程序之间不一致,“块状态”中止
 | 
			
		||||
 | 
			
		||||
0xD0C9
 | 
			
		||||
 | 
			
		||||
通过复位OB90退出状态区域
 | 
			
		||||
 | 
			
		||||
0xD0CA
 | 
			
		||||
 | 
			
		||||
通过在退出前重置OB90并访问错误读取标签退出状态范围
 | 
			
		||||
 | 
			
		||||
0xD0CB
 | 
			
		||||
 | 
			
		||||
外设输出的输出禁用再次激活
 | 
			
		||||
 | 
			
		||||
0xD0CC
 | 
			
		||||
 | 
			
		||||
调试功能的数据量受时间限制
 | 
			
		||||
 | 
			
		||||
0xD201
 | 
			
		||||
 | 
			
		||||
块名称中的语法错误
 | 
			
		||||
 | 
			
		||||
0xD202
 | 
			
		||||
 | 
			
		||||
函数参数中的语法错误
 | 
			
		||||
 | 
			
		||||
0xD205
 | 
			
		||||
 | 
			
		||||
RAM中已存在链接块:无法进行条件复制
 | 
			
		||||
 | 
			
		||||
0xD206
 | 
			
		||||
 | 
			
		||||
EPROM中已存在链接块:无法进行条件复制
 | 
			
		||||
 | 
			
		||||
0xD208
 | 
			
		||||
 | 
			
		||||
超出模块的最大复制(未链接)块数
 | 
			
		||||
 | 
			
		||||
0xD209
 | 
			
		||||
 | 
			
		||||
(至少)模块上找不到给定块之一
 | 
			
		||||
 | 
			
		||||
0xD20A
 | 
			
		||||
 | 
			
		||||
超出了可以与一个作业链接的最大块数
 | 
			
		||||
 | 
			
		||||
0xD20B
 | 
			
		||||
 | 
			
		||||
超出了一个作业可以删除的最大块数
 | 
			
		||||
 | 
			
		||||
0xD20C
 | 
			
		||||
 | 
			
		||||
OB无法复制,因为关联的优先级不存在
 | 
			
		||||
 | 
			
		||||
0xD20D
 | 
			
		||||
 | 
			
		||||
SDB无法解释(例如,未知数)
 | 
			
		||||
 | 
			
		||||
0xD20E
 | 
			
		||||
 | 
			
		||||
没有(进一步)阻止可用
 | 
			
		||||
 | 
			
		||||
0xD20F
 | 
			
		||||
 | 
			
		||||
超出模块特定的最大块大小
 | 
			
		||||
 | 
			
		||||
0xD210
 | 
			
		||||
 | 
			
		||||
块号无效
 | 
			
		||||
 | 
			
		||||
0xD212
 | 
			
		||||
 | 
			
		||||
标头属性不正确(与运行时相关)
 | 
			
		||||
 | 
			
		||||
0xD213
 | 
			
		||||
 | 
			
		||||
SDB太多。请注意对正在使用的模块的限制
 | 
			
		||||
 | 
			
		||||
0xD216
 | 
			
		||||
 | 
			
		||||
无效的用户程序 - 重置模块
 | 
			
		||||
 | 
			
		||||
0xD217
 | 
			
		||||
 | 
			
		||||
不允许在模块属性中指定的保护级别
 | 
			
		||||
 | 
			
		||||
0xD218
 | 
			
		||||
 | 
			
		||||
属性不正确(主动/被动)
 | 
			
		||||
 | 
			
		||||
0xD219
 | 
			
		||||
 | 
			
		||||
块长度不正确(例如,第一部分或整个块的长度不正确)
 | 
			
		||||
 | 
			
		||||
0xD21A
 | 
			
		||||
 | 
			
		||||
本地数据长度不正确或写保护错误
 | 
			
		||||
 | 
			
		||||
0xD21B
 | 
			
		||||
 | 
			
		||||
模块无法压缩或压缩早期中断
 | 
			
		||||
 | 
			
		||||
0xD21D
 | 
			
		||||
 | 
			
		||||
传输的动态项目数据量是非法的
 | 
			
		||||
 | 
			
		||||
0xD21E
 | 
			
		||||
 | 
			
		||||
无法为模块(例如FM,CP)分配参数。系统数据无法链接
 | 
			
		||||
 | 
			
		||||
0xD220
 | 
			
		||||
 | 
			
		||||
编程语言无效。请注意对正在使用的模块的限制
 | 
			
		||||
 | 
			
		||||
0xD221
 | 
			
		||||
 | 
			
		||||
连接或路由的系统数据无效
 | 
			
		||||
 | 
			
		||||
0xD222
 | 
			
		||||
 | 
			
		||||
全局数据定义的系统数据包含无效参数
 | 
			
		||||
 | 
			
		||||
0xD223
 | 
			
		||||
 | 
			
		||||
通信功能块的实例数据块错误或超出最大背景数据块数
 | 
			
		||||
 | 
			
		||||
0xD224
 | 
			
		||||
 | 
			
		||||
SCAN系统数据块包含无效参数
 | 
			
		||||
 | 
			
		||||
0xD225
 | 
			
		||||
 | 
			
		||||
DP系统数据块包含无效参数
 | 
			
		||||
 | 
			
		||||
0xD226
 | 
			
		||||
 | 
			
		||||
块中发生结构错误
 | 
			
		||||
 | 
			
		||||
0xD230
 | 
			
		||||
 | 
			
		||||
块中发生结构错误
 | 
			
		||||
 | 
			
		||||
0xD231
 | 
			
		||||
 | 
			
		||||
至少有一个已加载的OB无法复制,因为关联的优先级不存在
 | 
			
		||||
 | 
			
		||||
0xD232
 | 
			
		||||
 | 
			
		||||
加载块的至少一个块编号是非法的
 | 
			
		||||
 | 
			
		||||
0xD234
 | 
			
		||||
 | 
			
		||||
块在指定的内存介质或作业中存在两次
 | 
			
		||||
 | 
			
		||||
0xD235
 | 
			
		||||
 | 
			
		||||
该块包含不正确的校验和
 | 
			
		||||
 | 
			
		||||
0xD236
 | 
			
		||||
 | 
			
		||||
该块不包含校验和
 | 
			
		||||
 | 
			
		||||
0xD237
 | 
			
		||||
 | 
			
		||||
您将要加载块两次,即CPU上已存在具有相同时间戳的块
 | 
			
		||||
 | 
			
		||||
0xD238
 | 
			
		||||
 | 
			
		||||
指定的块中至少有一个不是DB
 | 
			
		||||
 | 
			
		||||
0xD239
 | 
			
		||||
 | 
			
		||||
至少有一个指定的DB在装载存储器中不可用作链接变量
 | 
			
		||||
 | 
			
		||||
0xD23A
 | 
			
		||||
 | 
			
		||||
至少有一个指定的DB与复制和链接的变体有很大不同
 | 
			
		||||
 | 
			
		||||
0xD240
 | 
			
		||||
 | 
			
		||||
违反了协调规则
 | 
			
		||||
 | 
			
		||||
0xD241
 | 
			
		||||
 | 
			
		||||
当前保护级别不允许该功能
 | 
			
		||||
 | 
			
		||||
0xD242
 | 
			
		||||
 | 
			
		||||
处理F块时的保护冲突
 | 
			
		||||
 | 
			
		||||
0xD250
 | 
			
		||||
 | 
			
		||||
更新和模块ID或版本不匹配
 | 
			
		||||
 | 
			
		||||
0xD251
 | 
			
		||||
 | 
			
		||||
操作系统组件序列不正确
 | 
			
		||||
 | 
			
		||||
0xD252
 | 
			
		||||
 | 
			
		||||
校验和错误
 | 
			
		||||
 | 
			
		||||
0xD253
 | 
			
		||||
 | 
			
		||||
没有可用的可执行加载程序; 只能使用存储卡进行更新
 | 
			
		||||
 | 
			
		||||
0xD254
 | 
			
		||||
 | 
			
		||||
操作系统中的存储错误
 | 
			
		||||
 | 
			
		||||
0xD280
 | 
			
		||||
 | 
			
		||||
在S7-300 CPU中编译块时出错
 | 
			
		||||
 | 
			
		||||
0xD2A1
 | 
			
		||||
 | 
			
		||||
块上的另一个块功能或触发器处于活动状态
 | 
			
		||||
 | 
			
		||||
0xD2A2
 | 
			
		||||
 | 
			
		||||
块上的触发器处于活动状态。首先完成调试功能
 | 
			
		||||
 | 
			
		||||
0xD2A3
 | 
			
		||||
 | 
			
		||||
块未激活(链接),块被占用或块当前被标记为删除
 | 
			
		||||
 | 
			
		||||
0xD2A4
 | 
			
		||||
 | 
			
		||||
该块已被另一个块函数处理
 | 
			
		||||
 | 
			
		||||
0xD2A6
 | 
			
		||||
 | 
			
		||||
无法同时保存和更改用户程序
 | 
			
		||||
 | 
			
		||||
0xD2A7
 | 
			
		||||
 | 
			
		||||
块具有“未链接”属性或未处理
 | 
			
		||||
 | 
			
		||||
0xD2A8
 | 
			
		||||
 | 
			
		||||
激活的调试功能阻止将参数分配给CPU
 | 
			
		||||
 | 
			
		||||
0xD2A9
 | 
			
		||||
 | 
			
		||||
正在为CPU分配新参数
 | 
			
		||||
 | 
			
		||||
0xD2AA
 | 
			
		||||
 | 
			
		||||
当前正在为模块分配新参数
 | 
			
		||||
 | 
			
		||||
0xD2AB
 | 
			
		||||
 | 
			
		||||
当前正在更改动态配置限制
 | 
			
		||||
 | 
			
		||||
0xD2AC
 | 
			
		||||
 | 
			
		||||
正在运行的激活或取消激活分配(SFC 12)暂时阻止R-KiR过程
 | 
			
		||||
 | 
			
		||||
0xD2B0
 | 
			
		||||
 | 
			
		||||
在RUN(CiR)中配置时发生错误
 | 
			
		||||
 | 
			
		||||
0xD2C0
 | 
			
		||||
 | 
			
		||||
已超出最大工艺对象数
 | 
			
		||||
 | 
			
		||||
0xD2C1
 | 
			
		||||
 | 
			
		||||
模块上已存在相同的技术数据块
 | 
			
		||||
 | 
			
		||||
0xD2C2
 | 
			
		||||
 | 
			
		||||
无法下载用户程序或下载硬件配置
 | 
			
		||||
 | 
			
		||||
0xD401
 | 
			
		||||
 | 
			
		||||
信息功能不可用
 | 
			
		||||
 | 
			
		||||
0xD402
 | 
			
		||||
 | 
			
		||||
信息功能不可用
 | 
			
		||||
 | 
			
		||||
0xD403
 | 
			
		||||
 | 
			
		||||
服务已登录/注销(诊断/ PMC)
 | 
			
		||||
 | 
			
		||||
0xD404
 | 
			
		||||
 | 
			
		||||
达到的最大节点数。不再需要登录诊断/ PMC
 | 
			
		||||
 | 
			
		||||
0xD405
 | 
			
		||||
 | 
			
		||||
不支持服务或函数参数中的语法错误
 | 
			
		||||
 | 
			
		||||
0xD406
 | 
			
		||||
 | 
			
		||||
当前不可用的必需信息
 | 
			
		||||
 | 
			
		||||
0xD407
 | 
			
		||||
 | 
			
		||||
发生诊断错误
 | 
			
		||||
 | 
			
		||||
0xD408
 | 
			
		||||
 | 
			
		||||
更新已中止
 | 
			
		||||
 | 
			
		||||
0xD409
 | 
			
		||||
 | 
			
		||||
DP总线错误
 | 
			
		||||
 | 
			
		||||
0xD601
 | 
			
		||||
 | 
			
		||||
函数参数中的语法错误
 | 
			
		||||
 | 
			
		||||
0xD602
 | 
			
		||||
 | 
			
		||||
输入的密码不正确
 | 
			
		||||
 | 
			
		||||
0xD603
 | 
			
		||||
 | 
			
		||||
连接已合法化
 | 
			
		||||
 | 
			
		||||
0xD604
 | 
			
		||||
 | 
			
		||||
已启用连接
 | 
			
		||||
 | 
			
		||||
0xD605
 | 
			
		||||
 | 
			
		||||
由于密码不存在,因此无法进行合法化
 | 
			
		||||
 | 
			
		||||
0xD801
 | 
			
		||||
 | 
			
		||||
至少有一个标记地址无效
 | 
			
		||||
 | 
			
		||||
0xD802
 | 
			
		||||
 | 
			
		||||
指定的作业不存在
 | 
			
		||||
 | 
			
		||||
0xD803
 | 
			
		||||
 | 
			
		||||
非法的工作状态
 | 
			
		||||
 | 
			
		||||
0xD804
 | 
			
		||||
 | 
			
		||||
非法循环时间(非法时基或多个)
 | 
			
		||||
 | 
			
		||||
0xD805
 | 
			
		||||
 | 
			
		||||
不能再设置循环读取作业
 | 
			
		||||
 | 
			
		||||
0xD806
 | 
			
		||||
 | 
			
		||||
引用的作业处于无法执行请求的功能的状态
 | 
			
		||||
 | 
			
		||||
0xD807
 | 
			
		||||
 | 
			
		||||
功能因过载而中止,这意味着执行读取周期所需的时间比设置的扫描周期时间长
 | 
			
		||||
 | 
			
		||||
0xDC01
 | 
			
		||||
 | 
			
		||||
日期和/或时间无效
 | 
			
		||||
 | 
			
		||||
0xE201
 | 
			
		||||
 | 
			
		||||
CPU已经是主设备
 | 
			
		||||
 | 
			
		||||
0xE202
 | 
			
		||||
 | 
			
		||||
由于闪存模块中的用户程序不同,无法进行连接和更新
 | 
			
		||||
 | 
			
		||||
0xE203
 | 
			
		||||
 | 
			
		||||
由于固件不同,无法连接和更新
 | 
			
		||||
 | 
			
		||||
0xE204
 | 
			
		||||
 | 
			
		||||
由于内存配置不同,无法连接和更新
 | 
			
		||||
 | 
			
		||||
0xE205
 | 
			
		||||
 | 
			
		||||
由于同步错误导致连接/更新中止
 | 
			
		||||
 | 
			
		||||
0xE206
 | 
			
		||||
 | 
			
		||||
由于协调违规而拒绝连接/更新
 | 
			
		||||
 | 
			
		||||
0xEF01
 | 
			
		||||
 | 
			
		||||
S7协议错误:ID2错误; 工作中只允许00H
 | 
			
		||||
 | 
			
		||||
0xEF02
 | 
			
		||||
 | 
			
		||||
S7协议错误:ID2错误; 资源集不存在
 | 
			
		||||
@@ -24,7 +24,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    public ReadWriteDevicesSerialSessionBase(SerialSession serialSession)
 | 
			
		||||
    {
 | 
			
		||||
        SerialSession = serialSession;
 | 
			
		||||
        WaitingClientEx = SerialSession.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
        WaitingClientEx = SerialSession.CreateWaitingClient(new() { });
 | 
			
		||||
        SerialSession.Received -= Received;
 | 
			
		||||
        SerialSession.Connecting -= Connecting;
 | 
			
		||||
        SerialSession.Connected -= Connected;
 | 
			
		||||
@@ -96,8 +96,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = SerialSession.GetWaitingClient(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)
 | 
			
		||||
@@ -111,8 +111,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = await SerialSession.GetWaitingClient(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)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    public ReadWriteDevicesTcpClientBase(TcpClient tcpClient)
 | 
			
		||||
    {
 | 
			
		||||
        TcpClient = tcpClient;
 | 
			
		||||
        WaitingClientEx = TcpClient.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
        WaitingClientEx = TcpClient.CreateWaitingClient(new() { });
 | 
			
		||||
        TcpClient.Connecting -= Connecting;
 | 
			
		||||
        TcpClient.Connected -= Connected;
 | 
			
		||||
        TcpClient.Disconnecting -= Disconnecting;
 | 
			
		||||
@@ -86,8 +86,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, };
 | 
			
		||||
            ResponsedData result = TcpClient.GetWaitingClient(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 };
 | 
			
		||||
            ResponsedData result = await TcpClient.GetWaitingClient(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)
 | 
			
		||||
@@ -137,13 +137,13 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
 | 
			
		||||
    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 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -55,7 +55,8 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override Task ConnectAsync(CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return Task.Run(() => TcpService.Start());
 | 
			
		||||
        Connect(cancellationToken);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -101,14 +102,14 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    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 Task Connecting(SocketClient client, ConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
 | 
			
		||||
        Logger?.Debug($"{client.IP}:{client.Port}正在连接");
 | 
			
		||||
        SetDataAdapter(client);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
@@ -116,14 +117,14 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    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 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        UdpSession = udpSession;
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        WaitingClientEx = UdpSession.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
        WaitingClientEx = UdpSession.CreateWaitingClient(new() { });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -64,8 +64,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = UdpSession.GetWaitingClient(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 };
 | 
			
		||||
            ResponsedData result = await UdpSession.GetWaitingClient(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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -180,6 +180,13 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override string ToString()
 | 
			
		||||
    {
 | 
			
		||||
        return Owner.ToString();
 | 
			
		||||
        if (Owner is SocketClient client)
 | 
			
		||||
        {
 | 
			
		||||
            return client.GetIPPort();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return Owner.ToString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
@@ -114,17 +115,47 @@ public static class StringExtensions
 | 
			
		||||
        else if (propertyType == typeof(sbyte))
 | 
			
		||||
            _value = sbyte.Parse(value);
 | 
			
		||||
        else if (propertyType == typeof(short))
 | 
			
		||||
            _value = short.Parse(value);
 | 
			
		||||
        {
 | 
			
		||||
            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                _value = short.Parse(value.Substring(2), NumberStyles.HexNumber);
 | 
			
		||||
            else
 | 
			
		||||
                _value = short.Parse(value);
 | 
			
		||||
        }
 | 
			
		||||
        else if (propertyType == typeof(ushort))
 | 
			
		||||
            _value = ushort.Parse(value);
 | 
			
		||||
        {
 | 
			
		||||
            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                _value = ushort.Parse(value.Substring(2), NumberStyles.HexNumber);
 | 
			
		||||
            else
 | 
			
		||||
                _value = ushort.Parse(value);
 | 
			
		||||
        }
 | 
			
		||||
        else if (propertyType == typeof(int))
 | 
			
		||||
            _value = int.Parse(value);
 | 
			
		||||
        {
 | 
			
		||||
            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                _value = int.Parse(value.Substring(2), NumberStyles.HexNumber);
 | 
			
		||||
            else
 | 
			
		||||
                _value = int.Parse(value);
 | 
			
		||||
        }
 | 
			
		||||
        else if (propertyType == typeof(uint))
 | 
			
		||||
            _value = uint.Parse(value);
 | 
			
		||||
        {
 | 
			
		||||
            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                _value = uint.Parse(value.Substring(2), NumberStyles.HexNumber);
 | 
			
		||||
            else
 | 
			
		||||
                _value = uint.Parse(value);
 | 
			
		||||
        }
 | 
			
		||||
        else if (propertyType == typeof(long))
 | 
			
		||||
            _value = long.Parse(value);
 | 
			
		||||
        {
 | 
			
		||||
            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                _value = long.Parse(value.Substring(2), NumberStyles.HexNumber);
 | 
			
		||||
            else
 | 
			
		||||
                _value = long.Parse(value);
 | 
			
		||||
        }
 | 
			
		||||
        else if (propertyType == typeof(ulong))
 | 
			
		||||
            _value = ulong.Parse(value);
 | 
			
		||||
        {
 | 
			
		||||
            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                _value = ulong.Parse(value.Substring(2), NumberStyles.HexNumber);
 | 
			
		||||
            else
 | 
			
		||||
                _value = ulong.Parse(value);
 | 
			
		||||
        }
 | 
			
		||||
        else if (propertyType == typeof(float))
 | 
			
		||||
            _value = float.Parse(value);
 | 
			
		||||
        else if (propertyType == typeof(double))
 | 
			
		||||
@@ -142,7 +173,6 @@ public static class StringExtensions
 | 
			
		||||
        else if (propertyType.IsEnum)
 | 
			
		||||
            _value = Enum.Parse(propertyType, value);
 | 
			
		||||
        return _value;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -27,8 +27,7 @@ using System.Runtime.CompilerServices;
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 具有释放的对象。
 | 
			
		||||
    /// 并未实现析构函数相关。
 | 
			
		||||
    /// 具有释放的对象。内部实现了GC.SuppressFinalize,但不包括析构函数相关。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public partial class DisposableObject : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                this.OnError(ex.Message);
 | 
			
		||||
                this.OnError(ex.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -189,7 +189,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static IEnumerable<string> GetTupleElementNames(this ParameterInfo parameter)
 | 
			
		||||
        {
 | 
			
		||||
            return ((dynamic)parameter.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")))?.TransformNames;
 | 
			
		||||
            return (IEnumerable<string>)DynamicMethodMemberAccessor.Default.GetValue(parameter.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")), "TransformNames");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -199,7 +199,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static IEnumerable<string> GetTupleElementNames(this MemberInfo memberInfo)
 | 
			
		||||
        {
 | 
			
		||||
            return ((dynamic)memberInfo.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")))?.TransformNames;
 | 
			
		||||
            return (IEnumerable<string>)DynamicMethodMemberAccessor.Default.GetValue(memberInfo.GetCustomAttribute(Type.GetType("System.Runtime.CompilerServices.TupleElementNamesAttribute")), "TransformNames");
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -49,5 +51,27 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        {
 | 
			
		||||
            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>
 | 
			
		||||
    /// 输出警示日志
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
@@ -55,12 +56,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var capacity = 0L;
 | 
			
		||||
            var poolId = this.Id;
 | 
			
		||||
            var maxBuckets = SelectBucketIndex(maxArrayLength);
 | 
			
		||||
            var buckets = new Bucket[maxBuckets + 1];
 | 
			
		||||
            for (var i = 0; i < buckets.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                buckets[i] = new Bucket(GetMaxSizeForBucket(i), maxArraysPerBucket, poolId);
 | 
			
		||||
                buckets[i] = new Bucket(GetMaxSizeForBucket(i), maxArraysPerBucket);
 | 
			
		||||
                long num = GetMaxSizeForBucket(i) * maxArraysPerBucket;
 | 
			
		||||
                capacity += num;
 | 
			
		||||
            }
 | 
			
		||||
@@ -183,16 +183,19 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="size"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
        public static int HitSize(int size)
 | 
			
		||||
        {
 | 
			
		||||
            return GetMaxSizeForBucket(SelectBucketIndex(size));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
        internal static int GetMaxSizeForBucket(int binIndex)
 | 
			
		||||
        {
 | 
			
		||||
            return 16 << binIndex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
        internal static int SelectBucketIndex(int bufferSize)
 | 
			
		||||
        {
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
@@ -208,18 +211,16 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            internal readonly int m_bufferLength;
 | 
			
		||||
            private readonly int m_numberOfBuffers;
 | 
			
		||||
            private T[][] m_buffers;
 | 
			
		||||
            private readonly int m_poolId;
 | 
			
		||||
 | 
			
		||||
            private int m_index;
 | 
			
		||||
            private SpinLock m_lock;
 | 
			
		||||
 | 
			
		||||
            internal Bucket(int bufferLength, int numberOfBuffers, int poolId)
 | 
			
		||||
            internal Bucket(int bufferLength, int numberOfBuffers)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_lock = new SpinLock(Debugger.IsAttached);
 | 
			
		||||
                this.m_buffers = new T[numberOfBuffers][];
 | 
			
		||||
                this.m_bufferLength = bufferLength;
 | 
			
		||||
                this.m_numberOfBuffers = numberOfBuffers;
 | 
			
		||||
                this.m_poolId = poolId;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public void Clear()
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 内存池
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class BytePool : ArrayPool<byte>
 | 
			
		||||
    public sealed class BytePool : ArrayPool<byte>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Timer m_timer;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 属性
 | 
			
		||||
@@ -118,32 +123,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual void Close(bool sendClose, string message)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        if (sendClose)
 | 
			
		||||
                        {
 | 
			
		||||
                            this.SendString(0, message);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                    }
 | 
			
		||||
                    this.IsHandshaked = false;
 | 
			
		||||
                    this.WaitHandlePool.CancelAll();
 | 
			
		||||
                    this.OnClose?.Invoke(this, message);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 建立对点
 | 
			
		||||
@@ -165,7 +144,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                Metadata = metadata
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.OnHandshaking?.Invoke(this, args);
 | 
			
		||||
            this.OnHandshaking(args).GetFalseAwaitResult();
 | 
			
		||||
 | 
			
		||||
            var waitVerify = new WaitVerify()
 | 
			
		||||
            {
 | 
			
		||||
@@ -189,7 +168,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 +181,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 +217,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                Metadata = metadata
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.OnHandshaking?.Invoke(this, args);
 | 
			
		||||
            await this.OnHandshaking(args).ConfigureFalseAwait();
 | 
			
		||||
 | 
			
		||||
            var waitVerify = new WaitVerify()
 | 
			
		||||
            {
 | 
			
		||||
@@ -253,8 +230,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 +240,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 +252,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 +269,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 +436,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 +444,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 +459,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 +471,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 +516,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 +525,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 +553,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 +576,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 +592,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 +616,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 +661,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 +677,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 +703,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 +716,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 +751,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 +765,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 +792,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 +822,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 +869,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 +915,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 +950,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 +1003,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:
 | 
			
		||||
                        {
 | 
			
		||||
@@ -971,7 +1032,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 重写
 | 
			
		||||
        #region 断开
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
@@ -979,19 +1040,36 @@ 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);
 | 
			
		||||
        }
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public void Close(string msg)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnClosed(true, msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public bool SendClose(string msg)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.SendString(0, msg);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion 重写
 | 
			
		||||
 | 
			
		||||
        #region 协议同步发送
 | 
			
		||||
@@ -1005,7 +1083,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 +1100,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 +1147,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 +1165,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 +1188,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 +1296,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 +1362,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 +1375,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 +1431,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 +1442,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 方法
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -17,17 +17,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 +45,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 +82,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 +149,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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 最大传输速度。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public long MaxSpeed { get => this.m_flowGate.Maximum; set => this.m_flowGate.Maximum = value; }
 | 
			
		||||
        public virtual long MaxSpeed { get => this.m_flowGate.Maximum; set => this.m_flowGate.Maximum = value; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 元数据
 | 
			
		||||
 
 | 
			
		||||
@@ -33,19 +33,19 @@ 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 字段
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.Id"/>
 | 
			
		||||
        public string Id => this.DmtpActor.Id;
 | 
			
		||||
        public string Id => this.m_dmtpActor.Id;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
        public bool IsHandshaked => this.m_dmtpActor != null && this.m_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;
 | 
			
		||||
@@ -184,7 +184,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                }
 | 
			
		||||
                if (!this.Online)
 | 
			
		||||
                {
 | 
			
		||||
                    await base.ConnectAsync(timeout, token);
 | 
			
		||||
                    await base.ConnectAsync(timeout);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var request = new HttpRequest()
 | 
			
		||||
@@ -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,19 +215,47 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #endregion 连接
 | 
			
		||||
 | 
			
		||||
        #region 断开
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.SafeDispose();
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_dmtpActor?.SafeDispose();
 | 
			
		||||
            }
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="msg"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                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 (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
                if (!await this.m_dmtpActor.InputReceivedData(message))
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.PluginsManager.Enable)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -250,25 +278,19 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            await 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 +299,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 = this.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 +347,11 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        #region 事件触发
 | 
			
		||||
@@ -358,32 +360,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 字段
 | 
			
		||||
 | 
			
		||||
@@ -68,17 +68,28 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            await base.OnConnected(socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IDmtpActor OnServiceFindDmtpActor(string id)
 | 
			
		||||
        {
 | 
			
		||||
            return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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,97 +49,67 @@ 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);
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message)
 | 
			
		||||
            {
 | 
			
		||||
                if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
                {
 | 
			
		||||
                    await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor?.Close(false, e.Message);
 | 
			
		||||
            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>
 | 
			
		||||
@@ -158,66 +128,73 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            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)
 | 
			
		||||
            {
 | 
			
		||||
@@ -228,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 内部委托绑定
 | 
			
		||||
@@ -257,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,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -39,22 +39,24 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_dmtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.Id"/>
 | 
			
		||||
        public string Id => this.DmtpActor.Id;
 | 
			
		||||
        public string Id => this.m_dmtpActor.Id;
 | 
			
		||||
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private SealedDmtpActor m_smtpActor;
 | 
			
		||||
        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;
 | 
			
		||||
        public bool IsHandshaked => this.m_dmtpActor != null && this.m_dmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        #region 断开
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
@@ -63,10 +65,33 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override void Close(string msg = "")
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.Close(true, msg);
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_dmtpActor?.SendClose(msg);
 | 
			
		||||
                this.m_dmtpActor?.Close(msg);
 | 
			
		||||
            }
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                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>
 | 
			
		||||
@@ -87,7 +112,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;
 | 
			
		||||
            }
 | 
			
		||||
@@ -107,7 +132,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;
 | 
			
		||||
            }
 | 
			
		||||
@@ -129,11 +154,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
 | 
			
		||||
@@ -154,11 +178,10 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                }
 | 
			
		||||
                if (!this.Online)
 | 
			
		||||
                {
 | 
			
		||||
                    await base.ConnectAsync(timeout, token);
 | 
			
		||||
                    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
 | 
			
		||||
@@ -174,13 +197,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
 | 
			
		||||
@@ -229,13 +252,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #endregion 发送
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void LoadConfig(TouchSocketConfig config)
 | 
			
		||||
        {
 | 
			
		||||
@@ -246,37 +262,31 @@ 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 async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
            this.DmtpActor.Close(false, e.Message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var message = (DmtpMessage)e.RequestInfo;
 | 
			
		||||
            if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
            if (!await this.m_dmtpActor.InputReceivedData(message).ConfigureFalseAwait())
 | 
			
		||||
            {
 | 
			
		||||
                await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
            await base.ReceivedData(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 内部委托绑定
 | 
			
		||||
@@ -286,52 +296,35 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnCreateChannel(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e);
 | 
			
		||||
            this.BreakOut(false, msg);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaked(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            return this.OnCreatedChannel(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnHandshaking(e);
 | 
			
		||||
            if (e.Handled)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e);
 | 
			
		||||
            return this.OnHandshaked(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
            return this.OnHandshaking(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
@@ -342,32 +335,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 字段
 | 
			
		||||
 | 
			
		||||
@@ -73,14 +73,25 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute)
 | 
			
		||||
            {
 | 
			
		||||
                Id = e.Id,
 | 
			
		||||
                OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null
 | 
			
		||||
                FindDmtpActor = this.FindDmtpActor
 | 
			
		||||
            });
 | 
			
		||||
            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
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_dmtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
@@ -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,99 +101,147 @@ 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);
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_dmtpActor?.SendClose(msg);
 | 
			
		||||
                this.m_dmtpActor?.Close(msg);
 | 
			
		||||
            }
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_dmtpActor?.SafeDispose();
 | 
			
		||||
            }
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.IsHandshaked)
 | 
			
		||||
            {
 | 
			
		||||
                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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.SafeDispose();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
            this.m_dmtpActor = actor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var message = (DmtpMessage)e.RequestInfo;
 | 
			
		||||
            if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
            if (!await this.m_dmtpActor.InputReceivedData(message).ConfigureFalseAwait())
 | 
			
		||||
            {
 | 
			
		||||
                await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
                await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
            await base.ReceivedData(e).ConfigureFalseAwait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnConnected(ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.Id = this.Id;
 | 
			
		||||
            await base.OnConnected(e);
 | 
			
		||||
            this.m_dmtpActor.Id = this.Id;
 | 
			
		||||
            await base.OnConnected(e).ConfigureFalseAwait();
 | 
			
		||||
 | 
			
		||||
            _ = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(this.VerifyTimeout);
 | 
			
		||||
                await Task.Delay(this.VerifyTimeout).ConfigureFalseAwait();
 | 
			
		||||
                if (!this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    this.TryShutdown();
 | 
			
		||||
@@ -228,21 +250,20 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.Close(false, e.Message);
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId)
 | 
			
		||||
        private Task ThisDmtpActorOutputSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(waitSetId.NewId);
 | 
			
		||||
            return base.SendAsync(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task ThisOnResetId(DmtpActor rpcActor, IdChangedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(e.NewId);
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 发送
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var message = DmtpMessage.CreateFrom(e.ByteBlock);
 | 
			
		||||
            if (!client.InputReceivedData(message))
 | 
			
		||||
            if (!await client.InputReceivedData(message))
 | 
			
		||||
            {
 | 
			
		||||
                if (this.PluginsManager.Enable)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -45,16 +45,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 +118,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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -50,13 +50,17 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        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/>
 | 
			
		||||
@@ -90,25 +94,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>
 | 
			
		||||
@@ -116,56 +116,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/>
 | 
			
		||||
@@ -173,7 +132,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await this.m_semaphore.WaitAsync();
 | 
			
		||||
                await this.m_semaphoreForConnect.WaitAsync();
 | 
			
		||||
                if (this.IsHandshaked)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -188,17 +147,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
 | 
			
		||||
                    };
 | 
			
		||||
@@ -212,7 +172,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.m_semaphore.Release();
 | 
			
		||||
                this.m_semaphoreForConnect.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -316,7 +276,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);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@@ -338,7 +298,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));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -388,12 +348,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)
 | 
			
		||||
@@ -404,7 +364,7 @@ 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())
 | 
			
		||||
            {
 | 
			
		||||
                this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
            }
 | 
			
		||||
@@ -412,71 +372,81 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
        #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 内部委托绑定
 | 
			
		||||
@@ -487,38 +457,68 @@ 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>
 | 
			
		||||
@@ -529,15 +529,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            throw new NotSupportedException("不支持该功能");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 不支持该功能
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="NotSupportedException"></exception>
 | 
			
		||||
        public void ClearReceiver()
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("不支持该功能");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
        #endregion Receiver
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,9 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,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 +61,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,9 +73,9 @@ 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);
 | 
			
		||||
                                return true;
 | 
			
		||||
@@ -101,7 +97,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        waitFileResource.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource);
 | 
			
		||||
                        _ = Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -118,7 +114,7 @@ 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);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -143,9 +139,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 +149,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 +173,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 +198,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 +217,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 +239,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 +264,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 +274,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 +299,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 +324,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 +334,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 +357,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 +382,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 +401,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);
 | 
			
		||||
                        _ = Task.Factory.StartNew(this.RequestPullSmallFile, waitSmallFilePackage);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -427,9 +423,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 +448,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 +468,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 +491,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 +564,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 +590,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 +617,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 +644,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 +671,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 +707,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 +1253,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)
 | 
			
		||||
@@ -1454,7 +1446,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
 | 
			
		||||
@@ -1528,7 +1520,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 +1557,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 +1819,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 +1883,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(
 | 
			
		||||
 
 | 
			
		||||
@@ -59,12 +59,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int TryCount { get; set; } = 10;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置结果状态
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="result"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public Result SetResult(Result result)
 | 
			
		||||
        internal Result SetResult(Result result)
 | 
			
		||||
        {
 | 
			
		||||
            this.Result = result;
 | 
			
		||||
            return result;
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,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 +56,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>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,10 @@ namespace ThingsGateway.Foundation.Dmtp.Redis
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// DmtpRedisActor
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        public DmtpRedisActor(IDmtpActor smtpActor)
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        public DmtpRedisActor(IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor = smtpActor;
 | 
			
		||||
            this.DmtpActor = dmtpActor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
@@ -241,7 +241,7 @@ namespace ThingsGateway.Foundation.Dmtp.Redis
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public bool InputReceivedData(DmtpMessage message)
 | 
			
		||||
        public async Task<bool> InputReceivedData(DmtpMessage message)
 | 
			
		||||
        {
 | 
			
		||||
            if (message.ProtocolFlags == this.m_redis_Request)
 | 
			
		||||
            {
 | 
			
		||||
@@ -311,7 +311,7 @@ namespace ThingsGateway.Foundation.Dmtp.Redis
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
                {
 | 
			
		||||
                    waitResult.Package(byteBlock);
 | 
			
		||||
                    this.DmtpActor.Send(this.m_redis_Response, byteBlock);
 | 
			
		||||
                    await this.DmtpActor.SendAsync(this.m_redis_Response, byteBlock);
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Resources;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Dmtp.Redis
 | 
			
		||||
@@ -52,16 +54,16 @@ namespace ThingsGateway.Foundation.Dmtp.Redis
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 从<see cref="DmtpActor"/>中获得<see cref="IDmtpRedisActor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static IDmtpRedisActor GetDmtpRedisActor(this IDmtpActor smtpActor)
 | 
			
		||||
        public static IDmtpRedisActor GetDmtpRedisActor(this IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            return smtpActor.GetValue(DmtpRedisActorProperty);
 | 
			
		||||
            return dmtpActor.GetValue(DmtpRedisActorProperty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static void SetStmpRedisActor(this IDmtpActor smtpActor, DmtpRedisActor redisClient)
 | 
			
		||||
        internal static void SetStmpRedisActor(this IDmtpActor dmtpActor, DmtpRedisActor redisClient)
 | 
			
		||||
        {
 | 
			
		||||
            smtpActor.SetValue(DmtpRedisActorProperty, redisClient);
 | 
			
		||||
            dmtpActor.SetValue(DmtpRedisActorProperty, redisClient);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -58,30 +58,30 @@ namespace ThingsGateway.Foundation.Dmtp.Redis
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var smtpRedisActor = new DmtpRedisActor(client.DmtpActor)
 | 
			
		||||
            var dmtpRedisActor = new DmtpRedisActor(client.DmtpActor)
 | 
			
		||||
            {
 | 
			
		||||
                ICache = this.ICache,
 | 
			
		||||
                Converter = this.Converter
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            smtpRedisActor.SetProtocolFlags(this.StartProtocol);
 | 
			
		||||
            client.DmtpActor.SetStmpRedisActor(smtpRedisActor);
 | 
			
		||||
            dmtpRedisActor.SetProtocolFlags(this.StartProtocol);
 | 
			
		||||
            client.DmtpActor.SetStmpRedisActor(dmtpRedisActor);
 | 
			
		||||
 | 
			
		||||
            return e.InvokeNext();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e)
 | 
			
		||||
        public async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (client.DmtpActor.GetDmtpRedisActor() is DmtpRedisActor redisClient)
 | 
			
		||||
            {
 | 
			
		||||
                if (redisClient.InputReceivedData(e.DmtpMessage))
 | 
			
		||||
                if (await redisClient.InputReceivedData(e.DmtpMessage))
 | 
			
		||||
                {
 | 
			
		||||
                    e.Handled = true;
 | 
			
		||||
                    return EasyTask.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return e.InvokeNext();
 | 
			
		||||
            await e.InvokeNext();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -36,10 +36,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建一个DmtpRpcActor
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        public DmtpRpcActor(IDmtpActor smtpActor)
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        public DmtpRpcActor(IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor = smtpActor;
 | 
			
		||||
            this.DmtpActor = dmtpActor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
@@ -69,7 +69,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public bool InputReceivedData(DmtpMessage message)
 | 
			
		||||
        public async Task<bool> InputReceivedData(DmtpMessage message)
 | 
			
		||||
        {
 | 
			
		||||
            var byteBlock = message.BodyByteBlock;
 | 
			
		||||
 | 
			
		||||
@@ -77,14 +77,13 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    //Console.WriteLine(byteBlock.Len);
 | 
			
		||||
                    var rpcPackage = new DmtpRpcPackage();
 | 
			
		||||
                    rpcPackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (rpcPackage.Route && this.DmtpActor.AllowRoute)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryRoute(RouteType.Rpc, rpcPackage))
 | 
			
		||||
                        if (await this.DmtpActor.TryRoute(new PackageRouterEventArgs(RouteType.Rpc, rpcPackage)).ConfigureFalseAwait())
 | 
			
		||||
                        {
 | 
			
		||||
                            if (this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId, out var actor))
 | 
			
		||||
                            if (await this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                            {
 | 
			
		||||
                                actor.Send(this.m_invoke_Request, byteBlock);
 | 
			
		||||
                                return true;
 | 
			
		||||
@@ -108,8 +107,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        rpcPackage.UnpackageBody(byteBlock);
 | 
			
		||||
                        Task.Factory.StartNew(this.InvokeThis, rpcPackage);
 | 
			
		||||
                        //this.InvokeThis(rpcPackage);
 | 
			
		||||
                        _ = Task.Factory.StartNew(this.InvokeThis, rpcPackage);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -126,7 +124,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    rpcPackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && rpcPackage.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(rpcPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_invoke_Response, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -151,7 +149,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    canceledPackage.UnpackageRouter(byteBlock);
 | 
			
		||||
                    if (this.DmtpActor.AllowRoute && canceledPackage.Route)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.DmtpActor.TryFindDmtpActor(canceledPackage.TargetId, out var actor))
 | 
			
		||||
                        if (await this.DmtpActor.TryFindDmtpActor(canceledPackage.TargetId).ConfigureFalseAwait() is DmtpActor actor)
 | 
			
		||||
                        {
 | 
			
		||||
                            actor.Send(this.m_cancelInvoke, byteBlock);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -203,7 +201,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var rpcPackage = (DmtpRpcPackage)o;
 | 
			
		||||
                //Console.WriteLine(rpcPackage.MethodName);
 | 
			
		||||
 | 
			
		||||
                var psData = rpcPackage.ParametersBytes;
 | 
			
		||||
                if (rpcPackage.Feedback == FeedbackType.WaitSend)
 | 
			
		||||
                {
 | 
			
		||||
@@ -227,7 +225,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
                var invokeResult = new InvokeResult();
 | 
			
		||||
                object[] ps = null;
 | 
			
		||||
                var methodInstance = this.GetInvokeMethod?.Invoke(rpcPackage.MethodName);
 | 
			
		||||
                var methodInstance = this.GetInvokeMethod.Invoke(rpcPackage.MethodName);
 | 
			
		||||
                DmtpRpcCallContext callContext = null;
 | 
			
		||||
                if (methodInstance != null)
 | 
			
		||||
                {
 | 
			
		||||
@@ -242,7 +240,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                                DmtpRpcPackage = rpcPackage
 | 
			
		||||
                            };
 | 
			
		||||
                            this.TryAdd(rpcPackage.Sign, callContext);
 | 
			
		||||
                            if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
 | 
			
		||||
                            if (methodInstance.IncludeCallContext)
 | 
			
		||||
                            {
 | 
			
		||||
                                ps = new object[methodInstance.ParameterTypes.Length];
 | 
			
		||||
                                ps[0] = callContext;
 | 
			
		||||
@@ -283,7 +281,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    {
 | 
			
		||||
                        transientRpcServer.CallContext = callContext;
 | 
			
		||||
                    }
 | 
			
		||||
                    invokeResult = await RpcStore.ExecuteAsync(rpcServer, ps, callContext);
 | 
			
		||||
                    invokeResult = await RpcStore.ExecuteAsync(rpcServer, ps, callContext).ConfigureFalseAwait();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (rpcPackage.Feedback == FeedbackType.OnlySend)
 | 
			
		||||
@@ -316,7 +314,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                                rpcPackage.ParametersBytes = new List<byte[]>();
 | 
			
		||||
 | 
			
		||||
                                var i = 0;
 | 
			
		||||
                                if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
 | 
			
		||||
                                if (methodInstance.IncludeCallContext)
 | 
			
		||||
                                {
 | 
			
		||||
                                    i = 1;
 | 
			
		||||
                                }
 | 
			
		||||
@@ -369,24 +367,20 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool TryFindDmtpRpcActor(string targetId, out DmtpRpcActor rpcActor)
 | 
			
		||||
        private async Task<DmtpRpcActor> TryFindDmtpRpcActor(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.GetDmtpRpcActor() is DmtpRpcActor newActor)
 | 
			
		||||
                if (dmtpActor.GetDmtpRpcActor() is DmtpRpcActor newActor)
 | 
			
		||||
                {
 | 
			
		||||
                    rpcActor = newActor;
 | 
			
		||||
                    return true;
 | 
			
		||||
                    return newActor;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            rpcActor = default;
 | 
			
		||||
            return false;
 | 
			
		||||
            return default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Rpc
 | 
			
		||||
@@ -504,8 +498,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -532,7 +524,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -689,8 +680,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -722,7 +711,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -779,8 +767,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetWaitDataAsync(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -818,7 +804,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
                    case FeedbackType.WaitSend:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.SetRunning:
 | 
			
		||||
                                    break;
 | 
			
		||||
@@ -832,7 +818,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    case FeedbackType.WaitInvoke:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.SetRunning:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -898,7 +884,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -907,7 +892,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    case FeedbackType.WaitSend:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.Overtime:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -918,7 +903,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    case FeedbackType.WaitInvoke:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.SetRunning:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -961,7 +946,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var actor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                actor.Invoke(invokeKey, invokeOption, parameters);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -977,7 +962,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -1009,7 +993,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -1069,9 +1052,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.Invoke(returnType, invokeKey, invokeOption, parameters);
 | 
			
		||||
                return actor.Invoke(returnType, invokeKey, invokeOption, parameters);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var rpcPackage = new DmtpRpcPackage
 | 
			
		||||
@@ -1084,10 +1067,8 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
                {
 | 
			
		||||
                    if (invokeOption == default)
 | 
			
		||||
@@ -1116,7 +1097,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -1175,9 +1155,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                rpcActor.Invoke(invokeKey, invokeOption, ref parameters, types);
 | 
			
		||||
                actor.Invoke(invokeKey, invokeOption, ref parameters, types);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -1191,7 +1171,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -1219,7 +1198,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -1289,9 +1267,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId).GetFalseAwaitResult() is DmtpRpcActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return rpcActor.Invoke(returnType, invokeKey, invokeOption, ref parameters, types);
 | 
			
		||||
                return actor.Invoke(returnType, invokeKey, invokeOption, ref parameters, types);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var rpcPackage = new DmtpRpcPackage
 | 
			
		||||
@@ -1304,7 +1282,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -1330,7 +1307,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -1400,9 +1376,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var actor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && await this.TryFindDmtpRpcActor(targetId).ConfigureFalseAwait() is DmtpRpcActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                await actor.InvokeAsync(invokeKey, invokeOption, parameters);
 | 
			
		||||
                await actor.InvokeAsync(invokeKey, invokeOption, parameters).ConfigureFalseAwait();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -1416,7 +1392,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
            var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitDataAsync(rpcPackage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
@@ -1448,7 +1423,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -1456,7 +1430,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
                    case FeedbackType.WaitSend:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.SetRunning:
 | 
			
		||||
                                    break;
 | 
			
		||||
@@ -1470,7 +1444,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    case FeedbackType.WaitInvoke:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.SetRunning:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -1508,9 +1482,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && this.TryFindDmtpRpcActor(targetId, out var rpcActor))
 | 
			
		||||
            if (this.DmtpActor.AllowRoute && await this.TryFindDmtpRpcActor(targetId).ConfigureFalseAwait() is DmtpRpcActor actor)
 | 
			
		||||
            {
 | 
			
		||||
                return await rpcActor.InvokeAsync(returnType, invokeKey, invokeOption, parameters);
 | 
			
		||||
                return await actor.InvokeAsync(returnType, invokeKey, invokeOption, parameters).ConfigureFalseAwait();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var rpcPackage = new DmtpRpcPackage
 | 
			
		||||
@@ -1553,8 +1527,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                    this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                switch (invokeOption.FeedbackType)
 | 
			
		||||
                {
 | 
			
		||||
                    case FeedbackType.OnlySend:
 | 
			
		||||
@@ -1563,7 +1535,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    case FeedbackType.WaitSend:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.Overtime:
 | 
			
		||||
                                    {
 | 
			
		||||
@@ -1574,7 +1546,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    case FeedbackType.WaitInvoke:
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout))
 | 
			
		||||
                            switch (await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait())
 | 
			
		||||
                            {
 | 
			
		||||
                                case WaitDataStatus.SetRunning:
 | 
			
		||||
                                    {
 | 
			
		||||
 
 | 
			
		||||
@@ -42,11 +42,11 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpRpcActor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActor smtpActor)
 | 
			
		||||
        public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            return smtpActor.GetValue(DmtpRpcActorProperty);
 | 
			
		||||
            return dmtpActor.GetValue(DmtpRpcActorProperty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -57,12 +57,12 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        /// <exception cref="ArgumentNullException"></exception>
 | 
			
		||||
        public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActorObject client)
 | 
			
		||||
        {
 | 
			
		||||
            var smtpRpcActor = client.DmtpActor.GetDmtpRpcActor();
 | 
			
		||||
            if (smtpRpcActor is null)
 | 
			
		||||
            var dmtpRpcActor = client.DmtpActor.GetDmtpRpcActor();
 | 
			
		||||
            if (dmtpRpcActor is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(smtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription());
 | 
			
		||||
                throw new ArgumentNullException(nameof(dmtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription());
 | 
			
		||||
            }
 | 
			
		||||
            return smtpRpcActor;
 | 
			
		||||
            return dmtpRpcActor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -73,22 +73,22 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        /// <exception cref="ArgumentNullException"></exception>
 | 
			
		||||
        public static TDmtpRpcActor GetDmtpRpcActor<TDmtpRpcActor>(this IDmtpActorObject client) where TDmtpRpcActor : IDmtpRpcActor
 | 
			
		||||
        {
 | 
			
		||||
            var smtpRpcActor = client.DmtpActor.GetDmtpRpcActor();
 | 
			
		||||
            if (smtpRpcActor is null)
 | 
			
		||||
            var dmtpRpcActor = client.DmtpActor.GetDmtpRpcActor();
 | 
			
		||||
            if (dmtpRpcActor is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(smtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription());
 | 
			
		||||
                throw new ArgumentNullException(nameof(dmtpRpcActor), TouchSocketDmtpResource.DmtpRpcActorArgumentNull.GetDescription());
 | 
			
		||||
            }
 | 
			
		||||
            return (TDmtpRpcActor)smtpRpcActor;
 | 
			
		||||
            return (TDmtpRpcActor)dmtpRpcActor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 向<see cref="DmtpActor"/>中设置<see cref="IDmtpRpcActor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="smtpActor"></param>
 | 
			
		||||
        /// <param name="smtpRpcActor"></param>
 | 
			
		||||
        internal static void SetDmtpRpcActor(this IDmtpActor smtpActor, IDmtpRpcActor smtpRpcActor)
 | 
			
		||||
        /// <param name="dmtpActor"></param>
 | 
			
		||||
        /// <param name="dmtpRpcActor"></param>
 | 
			
		||||
        internal static void SetDmtpRpcActor(this IDmtpActor dmtpActor, IDmtpRpcActor dmtpRpcActor)
 | 
			
		||||
        {
 | 
			
		||||
            smtpActor.SetValue(DmtpRpcActorProperty, smtpRpcActor);
 | 
			
		||||
            dmtpActor.SetValue(DmtpRpcActorProperty, dmtpRpcActor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 插件扩展
 | 
			
		||||
 
 | 
			
		||||
@@ -94,9 +94,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
            return this.ActionMap.GetMethodInstance(name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private DmtpRpcActor PrivateCreateDmtpRpcActor(IDmtpActor smtpActor)
 | 
			
		||||
        private DmtpRpcActor PrivateCreateDmtpRpcActor(IDmtpActor dmtpActor)
 | 
			
		||||
        {
 | 
			
		||||
            return new DmtpRpcActor(smtpActor);
 | 
			
		||||
            return new DmtpRpcActor(dmtpActor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Rpc配置
 | 
			
		||||
@@ -135,31 +135,30 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
            pluginsManager.Add<IDmtpActorObject, DmtpMessageEventArgs>(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this.OnDmtpReceived);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e)
 | 
			
		||||
        private async Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var smtpRpcActor = CreateDmtpRpcActor(client.DmtpActor);
 | 
			
		||||
            smtpRpcActor.RpcStore = this.RpcStore;
 | 
			
		||||
            smtpRpcActor.SerializationSelector = this.SerializationSelector;
 | 
			
		||||
            smtpRpcActor.GetInvokeMethod = this.GetInvokeMethod;
 | 
			
		||||
            var dmtpRpcActor = this.CreateDmtpRpcActor(client.DmtpActor);
 | 
			
		||||
            dmtpRpcActor.RpcStore = this.RpcStore;
 | 
			
		||||
            dmtpRpcActor.SerializationSelector = this.SerializationSelector;
 | 
			
		||||
            dmtpRpcActor.GetInvokeMethod = this.GetInvokeMethod;
 | 
			
		||||
 | 
			
		||||
            smtpRpcActor.SetProtocolFlags(this.StartProtocol);
 | 
			
		||||
            client.DmtpActor.SetDmtpRpcActor(smtpRpcActor);
 | 
			
		||||
            dmtpRpcActor.SetProtocolFlags(this.StartProtocol);
 | 
			
		||||
            client.DmtpActor.SetDmtpRpcActor(dmtpRpcActor);
 | 
			
		||||
 | 
			
		||||
            return e.InvokeNext();
 | 
			
		||||
            await e.InvokeNext();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e)
 | 
			
		||||
        private async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (client.DmtpActor.GetDmtpRpcActor() is DmtpRpcActor smtpRpcActor)
 | 
			
		||||
            if (client.DmtpActor.GetDmtpRpcActor() is DmtpRpcActor dmtpRpcActor)
 | 
			
		||||
            {
 | 
			
		||||
                if (smtpRpcActor.InputReceivedData(e.DmtpMessage))
 | 
			
		||||
                if (await dmtpRpcActor.InputReceivedData(e.DmtpMessage).ConfigureFalseAwait())
 | 
			
		||||
                {
 | 
			
		||||
                    e.Handled = true;
 | 
			
		||||
                    return EasyTask.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return e.InvokeNext();
 | 
			
		||||
            await e.InvokeNext();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion Config
 | 
			
		||||
 
 | 
			
		||||
@@ -108,10 +108,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
 | 
			
		||||
        internal void LoadInvokeOption(IInvokeOption option)
 | 
			
		||||
        {
 | 
			
		||||
            if (option is DmtpInvokeOption smtpInvokeOption)
 | 
			
		||||
            if (option is DmtpInvokeOption dmtpInvokeOption)
 | 
			
		||||
            {
 | 
			
		||||
                this.Feedback = smtpInvokeOption.FeedbackType;
 | 
			
		||||
                this.SerializationType = smtpInvokeOption.SerializationType;
 | 
			
		||||
                this.Feedback = dmtpInvokeOption.FeedbackType;
 | 
			
		||||
                this.SerializationType = dmtpInvokeOption.SerializationType;
 | 
			
		||||
            }
 | 
			
		||||
            else if (option is InvokeOption invokeOption)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message"></param>
 | 
			
		||||
        /// <returns>当满足本协议时,应当返回<see langword="true"/>,其他时候应该返回<see langword="false"/>.</returns>
 | 
			
		||||
        public bool InputReceivedData(DmtpMessage message);
 | 
			
		||||
        public Task<bool> InputReceivedData(DmtpMessage message);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -58,7 +58,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                        failedCount++;
 | 
			
		||||
                        if (failedCount > this.MaxFailCount)
 | 
			
		||||
                        {
 | 
			
		||||
                            client.DmtpActor.Close(true, "自动心跳失败次数达到最大,已断开连接。");
 | 
			
		||||
                            client.DmtpActor.Close("自动心跳失败次数达到最大,已断开连接。");
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -18,8 +18,8 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
    public class DmtpRouteService : IDmtpRouteService
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 查找路由的委托
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<string, IDmtpActor> FindDmtpActor { get; set; }
 | 
			
		||||
        public Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,12 +31,26 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="func"></param>
 | 
			
		||||
        public static void AddDmtpRouteService(this IContainer container, Func<string, IDmtpActor> func)
 | 
			
		||||
        public static void AddDmtpRouteService(this IContainer container, Func<string, Task<IDmtpActor>> func)
 | 
			
		||||
        {
 | 
			
		||||
            container.RegisterSingleton<IDmtpRouteService>(new DmtpRouteService()
 | 
			
		||||
            {
 | 
			
		||||
                FindDmtpActor = func
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 添加基于设定委托的Dmtp路由服务。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="action"></param>
 | 
			
		||||
        public static void AddDmtpRouteService(this IContainer container, Func<string, IDmtpActor> action)
 | 
			
		||||
        {
 | 
			
		||||
            AddDmtpRouteService(container, async (id) =>
 | 
			
		||||
            {
 | 
			
		||||
                await EasyTask.CompletedTask;
 | 
			
		||||
                return action.Invoke(id);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 查找其他IDmtpActor
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Func<string, IDmtpActor> FindDmtpActor { get; set; }
 | 
			
		||||
        Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -374,7 +374,7 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static TResponse SetContentTypeFromFileName<TResponse>(this TResponse response, string fileName) where TResponse : HttpResponse
 | 
			
		||||
        {
 | 
			
		||||
            var contentDisposition = "attachment;" + "filename=" + System.Web.HttpUtility.UrlEncode(fileName);
 | 
			
		||||
            var contentDisposition = $"attachment;filename={System.Web.HttpUtility.UrlEncode(fileName)}";
 | 
			
		||||
            response.Headers.Add(HttpHeaders.ContentDisposition, contentDisposition);
 | 
			
		||||
            return response;
 | 
			
		||||
        }
 | 
			
		||||
@@ -429,7 +429,7 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
            using (var reader = FilePool.GetReader(filePath))
 | 
			
		||||
            {
 | 
			
		||||
                response.SetContentTypeByExtension(Path.GetExtension(filePath));
 | 
			
		||||
                var contentDisposition = "attachment;" + "filename=" + System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath));
 | 
			
		||||
                var contentDisposition = $"attachment;filename={System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath))}";
 | 
			
		||||
                response.Headers.Add(HttpHeaders.ContentDisposition, contentDisposition);
 | 
			
		||||
                response.Headers.Add(HttpHeaders.AcceptRanges, "bytes");
 | 
			
		||||
 | 
			
		||||
@@ -526,7 +526,7 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
            using (var reader = FilePool.GetReader(filePath))
 | 
			
		||||
            {
 | 
			
		||||
                context.Response.SetContentTypeByExtension(Path.GetExtension(filePath));
 | 
			
		||||
                var contentDisposition = "attachment;" + "filename=" + System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath));
 | 
			
		||||
                var contentDisposition = $"attachment;filename={System.Web.HttpUtility.UrlEncode(fileName ?? Path.GetFileName(filePath))}";
 | 
			
		||||
                context.Response.Headers.Add(HttpHeaders.ContentDisposition, contentDisposition);
 | 
			
		||||
                context.Response.Headers.Add(HttpHeaders.AcceptRanges, "bytes");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
        public HttpStaticPagePlugin()
 | 
			
		||||
        {
 | 
			
		||||
            this.FileCache = new FileCachePool();
 | 
			
		||||
            this.SetNavigateAction(request =>
 | 
			
		||||
            {
 | 
			
		||||
                return request.RelativeURL;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -81,15 +85,45 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
            this.FileCache.Clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重新导航
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<HttpRequest, Task<string>> NavigateAction { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设定重新导航
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="func"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public HttpStaticPagePlugin SetNavigateAction(Func<HttpRequest, Task<string>> func)
 | 
			
		||||
        {
 | 
			
		||||
            this.NavigateAction = func;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设定重新导航
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="func"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public HttpStaticPagePlugin SetNavigateAction(Func<HttpRequest, string> func)
 | 
			
		||||
        {
 | 
			
		||||
            this.NavigateAction = (request) =>
 | 
			
		||||
            {
 | 
			
		||||
                return Task.FromResult(func(request));
 | 
			
		||||
            };
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.FileCache.Find(e.Context.Request.RelativeURL, out var data))
 | 
			
		||||
            var url = await this.NavigateAction.Invoke(e.Context.Request);
 | 
			
		||||
            if (this.FileCache.Find(url, out var data))
 | 
			
		||||
            {
 | 
			
		||||
                e.Context.Response.SetStatus();
 | 
			
		||||
                if (this.ContentTypeProvider?.TryGetContentType(e.Context.Request.RelativeURL, out var result) != true)
 | 
			
		||||
                if (this.ContentTypeProvider?.TryGetContentType(url, out var result) != true)
 | 
			
		||||
                {
 | 
			
		||||
                    result = HttpTools.GetContentTypeFromExtension(e.Context.Request.RelativeURL);
 | 
			
		||||
                    result = HttpTools.GetContentTypeFromExtension(url);
 | 
			
		||||
                }
 | 
			
		||||
                e.Context.Response.ContentType = result;
 | 
			
		||||
                e.Context.Response.SetContentLength(data.Length)
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
            {
 | 
			
		||||
                return new WebSocketReceiveResult(this.ComplateRead, null);
 | 
			
		||||
            }
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token);
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token).ConfigureFalseAwait();
 | 
			
		||||
            return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame);
 | 
			
		||||
        }
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
@@ -82,7 +82,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
            {
 | 
			
		||||
                return new WebSocketReceiveResult(this.ComplateRead, null);
 | 
			
		||||
            }
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token);
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token).ConfigureFalseAwait();
 | 
			
		||||
            return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
@@ -146,7 +146,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if (await this.m_resetEventForComplateRead.WaitOneAsync(TimeSpan.FromSeconds(10)))
 | 
			
		||||
            if (await this.m_resetEventForComplateRead.WaitOneAsync(TimeSpan.FromSeconds(10)).ConfigureFalseAwait())
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                            args.Context.Response.Build(byteBlock);
 | 
			
		||||
                            await client.DefaultSendAsync(byteBlock).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        await client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), client, new HttpContextEventArgs(httpContext))
 | 
			
		||||
                        _ = client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), client, new HttpContextEventArgs(httpContext))
 | 
			
		||||
                            .ConfigureAwait(false);
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                if (await this.VerifyConnection.Invoke(client, e.Context))
 | 
			
		||||
                {
 | 
			
		||||
                    e.Handled = true;
 | 
			
		||||
                    _ = client.SwitchProtocolToWebSocket(e.Context);
 | 
			
		||||
                    await client.SwitchProtocolToWebSocket(e.Context);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 标识该接口将自动生成调用的扩展方法静态类
 | 
			
		||||
    /// 标识该接口将自动生成调用的代理类
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
 | 
			
		||||
    public sealed class GeneratorRpcProxyAttribute : Attribute
 | 
			
		||||
@@ -39,7 +39,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        public string Namespace { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 生成的类名,不要包含“I”,生成接口时会自动家。
 | 
			
		||||
        /// 生成的类名,不要包含“I”,生成接口时会自动添加。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string ClassName { get; set; }
 | 
			
		||||
 | 
			
		||||
@@ -48,11 +48,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public CodeGeneratorFlag GeneratorFlag { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 函数标识
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public MethodFlags MethodFlags { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 继承接口
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public RpcAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            this.MethodFlags = MethodFlags.None;
 | 
			
		||||
            this.Exceptions.Add(typeof(TimeoutException), "调用超时");
 | 
			
		||||
            this.Exceptions.Add(typeof(RpcInvokeException), "Rpc调用异常");
 | 
			
		||||
            this.Exceptions.Add(typeof(Exception), "其他异常");
 | 
			
		||||
@@ -72,11 +71,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string InvokeKey { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 函数标识
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public MethodFlags MethodFlags { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否仅以函数名调用,当为True是,调用时仅需要传入方法名即可。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -122,25 +116,25 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
 | 
			
		||||
                codeString.Append("public static ");
 | 
			
		||||
                codeString.Append(this.GetReturn(methodInstance, false));
 | 
			
		||||
                codeString.Append(" ");
 | 
			
		||||
                codeString.Append(' ');
 | 
			
		||||
                codeString.Append(this.GetMethodName(methodInstance, false));
 | 
			
		||||
                codeString.Append("<TClient>(");//方法参数
 | 
			
		||||
 | 
			
		||||
                codeString.Append($"this TClient client");
 | 
			
		||||
 | 
			
		||||
                codeString.Append(",");
 | 
			
		||||
                codeString.Append(',');
 | 
			
		||||
                for (var i = 0; i < parametersStr.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    codeString.Append(parametersStr[i]);
 | 
			
		||||
                }
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append(",");
 | 
			
		||||
                    codeString.Append(',');
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetInvokeOption());
 | 
			
		||||
                codeString.AppendLine(") where TClient:");
 | 
			
		||||
@@ -149,7 +143,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    codeString.Append(InterfaceTypes[i].FullName);
 | 
			
		||||
@@ -159,7 +153,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append($"object[] parameters = new object[]");
 | 
			
		||||
                    codeString.Append("{");
 | 
			
		||||
                    codeString.Append('{');
 | 
			
		||||
 | 
			
		||||
                    foreach (var parameter in parameters)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -173,7 +167,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                        if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append(",");
 | 
			
		||||
                            codeString.Append(',');
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.AppendLine("};");
 | 
			
		||||
@@ -181,13 +175,13 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append($"Type[] types = new Type[]");
 | 
			
		||||
                        codeString.Append("{");
 | 
			
		||||
                        codeString.Append('{');
 | 
			
		||||
                        foreach (var parameter in parameters)
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
 | 
			
		||||
                            if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                            {
 | 
			
		||||
                                codeString.Append(",");
 | 
			
		||||
                                codeString.Append(',');
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        codeString.AppendLine("};");
 | 
			
		||||
@@ -199,7 +193,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    if (parametersStr.Count == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, null);");
 | 
			
		||||
@@ -207,7 +201,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    else if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption,ref parameters,types);");
 | 
			
		||||
@@ -215,7 +209,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, parameters);");
 | 
			
		||||
@@ -275,12 +269,12 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //以下生成异步
 | 
			
		||||
            if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) && !isOut && !isRef)//没有out或者ref
 | 
			
		||||
            if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) /*&& !isOut && !isRef*/)
 | 
			
		||||
            {
 | 
			
		||||
                codeString.AppendLine("///<summary>");
 | 
			
		||||
                codeString.AppendLine($"///{description}");
 | 
			
		||||
                codeString.AppendLine("///</summary>");
 | 
			
		||||
                if (methodInstance.HasReturn)
 | 
			
		||||
                if (methodInstance.HasReturn && !isOut && !isRef)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append("public static async ");
 | 
			
		||||
                }
 | 
			
		||||
@@ -289,24 +283,24 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    codeString.Append("public static ");
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetReturn(methodInstance, true));
 | 
			
		||||
                codeString.Append(" ");
 | 
			
		||||
                codeString.Append(' ');
 | 
			
		||||
                codeString.Append(this.GetMethodName(methodInstance, true));
 | 
			
		||||
                codeString.Append("<TClient>(");//方法参数
 | 
			
		||||
 | 
			
		||||
                codeString.Append($"this TClient client");
 | 
			
		||||
 | 
			
		||||
                codeString.Append(",");
 | 
			
		||||
                codeString.Append(',');
 | 
			
		||||
                for (var i = 0; i < parametersStr.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.Append(parametersStr[i]);
 | 
			
		||||
                }
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append(",");
 | 
			
		||||
                    codeString.Append(',');
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetInvokeOption());
 | 
			
		||||
                codeString.AppendLine(") where TClient:");
 | 
			
		||||
@@ -315,7 +309,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    codeString.Append(InterfaceTypes[i].FullName);
 | 
			
		||||
@@ -326,16 +320,39 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append($"object[] parameters = new object[]");
 | 
			
		||||
                    codeString.Append("{");
 | 
			
		||||
                    codeString.Append('{');
 | 
			
		||||
 | 
			
		||||
                    foreach (var parameter in parameters)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(parameter.Name);
 | 
			
		||||
                        if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append($"default({this.GetProxyParameterName(parameter)})");
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append(parameter.Name);
 | 
			
		||||
                        }
 | 
			
		||||
                        if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append(",");
 | 
			
		||||
                            codeString.Append(',');
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.AppendLine("};");
 | 
			
		||||
 | 
			
		||||
                    if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append($"Type[] types = new Type[]");
 | 
			
		||||
                        codeString.Append('{');
 | 
			
		||||
                        foreach (var parameter in parameters)
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
 | 
			
		||||
                            if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                            {
 | 
			
		||||
                                codeString.Append(',');
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        codeString.AppendLine("};");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (methodInstance.HasReturn)
 | 
			
		||||
@@ -343,15 +360,23 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    if (parametersStr.Count == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("return ({0}) await client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, null);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption,ref parameters,types);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("return ({0}) await client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, parameters);");
 | 
			
		||||
@@ -365,6 +390,12 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, null);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append("client.Invoke(");
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption,ref parameters,types);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append("return client.InvokeAsync(");
 | 
			
		||||
@@ -372,6 +403,43 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, parameters);");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (isOut || isRef)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.AppendLine("if(parameters!=null)");
 | 
			
		||||
                    codeString.AppendLine("{");
 | 
			
		||||
                    for (var i = 0; i < parameters.Length; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i));
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.AppendLine("}");
 | 
			
		||||
                    if (isOut)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine("else");
 | 
			
		||||
                        codeString.AppendLine("{");
 | 
			
		||||
                        for (var i = 0; i < parameters.Length; i++)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (parameters[i].IsOut)
 | 
			
		||||
                            {
 | 
			
		||||
                                codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i])));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        codeString.AppendLine("}");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (isOut || isRef)
 | 
			
		||||
                {
 | 
			
		||||
                    if (methodInstance.HasReturn)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine(string.Format("return Task.FromResult<{0}>(returnData);", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine(string.Format("return  EasyTask.CompletedTask;"));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                codeString.AppendLine("}");
 | 
			
		||||
            }
 | 
			
		||||
            return codeString.ToString();
 | 
			
		||||
@@ -409,21 +477,21 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
 | 
			
		||||
                codeString.Append("public ");
 | 
			
		||||
                codeString.Append(this.GetReturn(methodInstance, false));
 | 
			
		||||
                codeString.Append(" ");
 | 
			
		||||
                codeString.Append(' ');
 | 
			
		||||
                codeString.Append(this.GetMethodName(methodInstance, false));
 | 
			
		||||
                codeString.Append("(");//方法参数
 | 
			
		||||
                codeString.Append('(');//方法参数
 | 
			
		||||
 | 
			
		||||
                for (var i = 0; i < parametersStr.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.Append(parametersStr[i]);
 | 
			
		||||
                }
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append(",");
 | 
			
		||||
                    codeString.Append(',');
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetInvokeOption());
 | 
			
		||||
                codeString.AppendLine(")");
 | 
			
		||||
@@ -438,7 +506,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append($"object[] parameters = new object[]");
 | 
			
		||||
                    codeString.Append("{");
 | 
			
		||||
                    codeString.Append('{');
 | 
			
		||||
 | 
			
		||||
                    foreach (var parameter in parameters)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -452,7 +520,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                        if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append(",");
 | 
			
		||||
                            codeString.Append(',');
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.AppendLine("};");
 | 
			
		||||
@@ -460,13 +528,13 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append($"Type[] types = new Type[]");
 | 
			
		||||
                        codeString.Append("{");
 | 
			
		||||
                        codeString.Append('{');
 | 
			
		||||
                        foreach (var parameter in parameters)
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
 | 
			
		||||
                            if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                            {
 | 
			
		||||
                                codeString.Append(",");
 | 
			
		||||
                                codeString.Append(',');
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        codeString.AppendLine("};");
 | 
			
		||||
@@ -478,7 +546,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    if (parametersStr.Count == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, null);");
 | 
			
		||||
@@ -554,12 +622,12 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //以下生成异步
 | 
			
		||||
            if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync) && !isOut && !isRef)//没有out或者ref
 | 
			
		||||
            if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync))
 | 
			
		||||
            {
 | 
			
		||||
                codeString.AppendLine("///<summary>");
 | 
			
		||||
                codeString.AppendLine($"///{description}");
 | 
			
		||||
                codeString.AppendLine("///</summary>");
 | 
			
		||||
                if (methodInstance.HasReturn)
 | 
			
		||||
                if (methodInstance.HasReturn && (!isOut && !isRef))
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append("public async ");
 | 
			
		||||
                }
 | 
			
		||||
@@ -568,21 +636,21 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    codeString.Append("public ");
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetReturn(methodInstance, true));
 | 
			
		||||
                codeString.Append(" ");
 | 
			
		||||
                codeString.Append(' ');
 | 
			
		||||
                codeString.Append(this.GetMethodName(methodInstance, true));
 | 
			
		||||
                codeString.Append("(");//方法参数
 | 
			
		||||
                codeString.Append('(');//方法参数
 | 
			
		||||
 | 
			
		||||
                for (var i = 0; i < parametersStr.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.Append(parametersStr[i]);
 | 
			
		||||
                }
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append(",");
 | 
			
		||||
                    codeString.Append(',');
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetInvokeOption());
 | 
			
		||||
                codeString.AppendLine(")");
 | 
			
		||||
@@ -597,16 +665,39 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                if (parametersStr.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append($"object[] parameters = new object[]");
 | 
			
		||||
                    codeString.Append("{");
 | 
			
		||||
                    codeString.Append('{');
 | 
			
		||||
 | 
			
		||||
                    foreach (var parameter in parameters)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(parameter.Name);
 | 
			
		||||
                        if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append($"default({this.GetProxyParameterName(parameter)})");
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append(parameter.Name);
 | 
			
		||||
                        }
 | 
			
		||||
                        if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append(",");
 | 
			
		||||
                            codeString.Append(',');
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.AppendLine("};");
 | 
			
		||||
 | 
			
		||||
                    if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append($"Type[] types = new Type[]");
 | 
			
		||||
                        codeString.Append('{');
 | 
			
		||||
                        foreach (var parameter in parameters)
 | 
			
		||||
                        {
 | 
			
		||||
                            codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
 | 
			
		||||
                            if (parameter != parameters[parameters.Length - 1])
 | 
			
		||||
                            {
 | 
			
		||||
                                codeString.Append(',');
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        codeString.AppendLine("};");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (methodInstance.HasReturn)
 | 
			
		||||
@@ -614,15 +705,23 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    if (parametersStr.Count == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("return ({0}) await Client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, null);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption,ref parameters,types);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(string.Format("return ({0}) await Client.InvokeAsync", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append("(");
 | 
			
		||||
                        codeString.Append('(');
 | 
			
		||||
                        codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, parameters);");
 | 
			
		||||
@@ -636,6 +735,12 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, null);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (isOut || isRef)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append("Client.Invoke(");
 | 
			
		||||
                        codeString.Append($"\"{this.GetInvokenKey(methodInstance)}\"");
 | 
			
		||||
                        codeString.AppendLine(",invokeOption,ref parameters,types);");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append("return Client.InvokeAsync(");
 | 
			
		||||
@@ -643,8 +748,46 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        codeString.AppendLine(",invokeOption, parameters);");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (isOut || isRef)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.AppendLine("if(parameters!=null)");
 | 
			
		||||
                    codeString.AppendLine("{");
 | 
			
		||||
                    for (var i = 0; i < parameters.Length; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i));
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.AppendLine("}");
 | 
			
		||||
                    if (isOut)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine("else");
 | 
			
		||||
                        codeString.AppendLine("{");
 | 
			
		||||
                        for (var i = 0; i < parameters.Length; i++)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (parameters[i].IsOut)
 | 
			
		||||
                            {
 | 
			
		||||
                                codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i])));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        codeString.AppendLine("}");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (isOut || isRef)
 | 
			
		||||
                {
 | 
			
		||||
                    if (methodInstance.HasReturn)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine(string.Format("return Task.FromResult<{0}>(returnData);", this.GetProxyParameterName(methodInstance.Info.ReturnParameter)));
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.AppendLine(string.Format("return  EasyTask.CompletedTask;"));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                codeString.AppendLine("}");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            return codeString.ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -669,26 +812,26 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                codeString.Append(this.GetReturn(methodInstance, false));
 | 
			
		||||
                codeString.Append(" ");
 | 
			
		||||
                codeString.Append(' ');
 | 
			
		||||
                codeString.Append(this.GetMethodName(methodInstance, false));
 | 
			
		||||
                codeString.Append("(");//方法参数
 | 
			
		||||
                codeString.Append('(');//方法参数
 | 
			
		||||
                for (var i = 0; i < parameters.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.Append(parameters[i]);
 | 
			
		||||
                }
 | 
			
		||||
                if (parameters.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append(",");
 | 
			
		||||
                    codeString.Append(',');
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetInvokeOption());
 | 
			
		||||
                codeString.AppendLine(");");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync) && !isOut && !isRef)//没有out或者ref
 | 
			
		||||
            if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync))
 | 
			
		||||
            {
 | 
			
		||||
                codeString.AppendLine("///<summary>");
 | 
			
		||||
                codeString.AppendLine($"///{description}");
 | 
			
		||||
@@ -699,21 +842,21 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                codeString.Append(this.GetReturn(methodInstance, true));
 | 
			
		||||
                codeString.Append(" ");
 | 
			
		||||
                codeString.Append(' ');
 | 
			
		||||
                codeString.Append(this.GetMethodName(methodInstance, true));
 | 
			
		||||
                codeString.Append("(");//方法参数
 | 
			
		||||
                codeString.Append('(');//方法参数
 | 
			
		||||
 | 
			
		||||
                for (var i = 0; i < parameters.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (i > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        codeString.Append(",");
 | 
			
		||||
                        codeString.Append(',');
 | 
			
		||||
                    }
 | 
			
		||||
                    codeString.Append(parameters[i]);
 | 
			
		||||
                }
 | 
			
		||||
                if (parameters.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    codeString.Append(",");
 | 
			
		||||
                    codeString.Append(',');
 | 
			
		||||
                }
 | 
			
		||||
                codeString.Append(this.GetInvokeOption());
 | 
			
		||||
                codeString.AppendLine(");");
 | 
			
		||||
@@ -774,7 +917,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            isOut = false;
 | 
			
		||||
            isRef = false;
 | 
			
		||||
 | 
			
		||||
            if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
 | 
			
		||||
            if (methodInstance.IncludeCallContext)
 | 
			
		||||
            {
 | 
			
		||||
                var infos = new List<ParameterInfo>(methodInstance.Parameters);
 | 
			
		||||
                infos.RemoveAt(0);
 | 
			
		||||
 
 | 
			
		||||
@@ -302,7 +302,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        var i = 0;
 | 
			
		||||
                        if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
 | 
			
		||||
                        if (methodInstance.IncludeCallContext)
 | 
			
		||||
                        {
 | 
			
		||||
                            i = 1;
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -75,10 +75,10 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var fromMethodInfos = new Dictionary<string, MethodInfo>();
 | 
			
		||||
            CodeGenerator.GetMethodInfos(ServerFromType, ref fromMethodInfos);
 | 
			
		||||
            CodeGenerator.GetMethodInfos(this.ServerFromType, ref fromMethodInfos);
 | 
			
		||||
 | 
			
		||||
            var toMethodInfos = new Dictionary<string, MethodInfo>();
 | 
			
		||||
            CodeGenerator.GetMethodInfos(ServerToType, ref toMethodInfos);
 | 
			
		||||
            CodeGenerator.GetMethodInfos(this.ServerToType, ref toMethodInfos);
 | 
			
		||||
 | 
			
		||||
            var attributes = method.GetCustomAttributes<RpcAttribute>(true);
 | 
			
		||||
            if (attributes.Any())
 | 
			
		||||
@@ -98,7 +98,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                foreach (var item in ServerFromType.GetCustomAttributes(true))
 | 
			
		||||
                foreach (var item in this.ServerFromType.GetCustomAttributes(true))
 | 
			
		||||
                {
 | 
			
		||||
                    if (item is IRpcActionFilter filter)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (ServerFromType != ServerToType)
 | 
			
		||||
                if (this.ServerFromType != this.ServerToType)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var item in toMethod.GetCustomAttributes(true))
 | 
			
		||||
                    {
 | 
			
		||||
@@ -116,7 +116,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    foreach (var item in ServerToType.GetCustomAttributes(true))
 | 
			
		||||
                    foreach (var item in this.ServerToType.GetCustomAttributes(true))
 | 
			
		||||
                    {
 | 
			
		||||
                        if (item is IRpcActionFilter filter)
 | 
			
		||||
                        {
 | 
			
		||||
@@ -128,17 +128,23 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
                {
 | 
			
		||||
                    this.Filters = actionFilters.ToArray();
 | 
			
		||||
                }
 | 
			
		||||
                foreach (var item in attributes)
 | 
			
		||||
                //foreach (var item in attributes)
 | 
			
		||||
                //{
 | 
			
		||||
                //    this.MethodFlags |= item.MethodFlags;
 | 
			
		||||
                //}
 | 
			
		||||
                //if (this.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
 | 
			
		||||
                //{
 | 
			
		||||
                //    if (this.Parameters.Length == 0 || !typeof(ICallContext).IsAssignableFrom(this.Parameters[0].ParameterType))
 | 
			
		||||
                //    {
 | 
			
		||||
                //        throw new RpcException($"函数:{method},标识包含{MethodFlags.IncludeCallContext}时,必须包含{nameof(ICallContext)}或其派生类参数,且为第一参数。");
 | 
			
		||||
                //    }
 | 
			
		||||
                //}
 | 
			
		||||
 | 
			
		||||
                if (this.Parameters.Length > 0 && typeof(ICallContext).IsAssignableFrom(this.Parameters[0].ParameterType))
 | 
			
		||||
                {
 | 
			
		||||
                    this.MethodFlags |= item.MethodFlags;
 | 
			
		||||
                }
 | 
			
		||||
                if (this.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.Parameters.Length == 0 || !typeof(ICallContext).IsAssignableFrom(this.Parameters[0].ParameterType))
 | 
			
		||||
                    {
 | 
			
		||||
                        throw new RpcException($"函数:{method},标识包含{MethodFlags.IncludeCallContext}时,必须包含{nameof(ICallContext)}或其派生类参数,且为第一参数。");
 | 
			
		||||
                    }
 | 
			
		||||
                    this.IncludeCallContext = true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var names = new List<string>();
 | 
			
		||||
                foreach (var parameterInfo in this.Parameters)
 | 
			
		||||
                {
 | 
			
		||||
@@ -155,6 +161,11 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否包含调用上下文
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IncludeCallContext { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 筛选器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -165,11 +176,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsEnable { get; set; } = true;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 函数标识
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public MethodFlags MethodFlags { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 参数名集合
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -130,7 +130,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            catch (TargetInvocationException ex)
 | 
			
		||||
            {
 | 
			
		||||
                invokeResult.Status = InvokeStatus.InvocationException;
 | 
			
		||||
                invokeResult.Message = ex.InnerException != null ? "函数内部发生异常,信息:" + ex.InnerException.Message : "函数内部发生异常,信息:未知";
 | 
			
		||||
                invokeResult.Message = ex.InnerException != null ? $"函数内部发生异常,信息:{ex.InnerException.Message}" : "函数内部发生异常,信息:未知";
 | 
			
		||||
                if (callContext.MethodInstance.Filters != null)
 | 
			
		||||
                {
 | 
			
		||||
                    for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
 | 
			
		||||
@@ -223,7 +223,7 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
            catch (TargetInvocationException ex)
 | 
			
		||||
            {
 | 
			
		||||
                invokeResult.Status = InvokeStatus.InvocationException;
 | 
			
		||||
                invokeResult.Message = ex.InnerException != null ? "函数内部发生异常,信息:" + ex.InnerException.Message : "函数内部发生异常,信息:未知";
 | 
			
		||||
                invokeResult.Message = ex.InnerException != null ? $"函数内部发生异常,信息:{ex.InnerException.Message}" : "函数内部发生异常,信息:未知";
 | 
			
		||||
                if (callContext.MethodInstance.Filters != null)
 | 
			
		||||
                {
 | 
			
		||||
                    for (var i = 0; i < callContext.MethodInstance.Filters.Length; i++)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#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.Rpc
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 函数标识
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Flags]
 | 
			
		||||
    public enum MethodFlags
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 空
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        None = 1,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 包含调用上下文
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IncludeCallContext = 2
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -34,8 +34,8 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// 调用此服务的主体。
 | 
			
		||||
        /// <para>
 | 
			
		||||
        /// <list type="bullet">
 | 
			
		||||
        /// <item>当该服务在<see cref="ITcpService"/>及派生中调用时,该值一般为<see cref="ISocketClient"/>对象。</item>
 | 
			
		||||
        /// <item>当该服务在<see cref="ITcpClient"/>及派生中调用时,该值一般为<see cref="ITcpClient"/>对象。</item>
 | 
			
		||||
        /// <item>当该服务在ITcpService及派生中调用时,该值一般为ISocketClient对象。</item>
 | 
			
		||||
        /// <item>当该服务在ITcpClient及派生中调用时,该值一般为ITcpClient对象。</item>
 | 
			
		||||
        /// </list>
 | 
			
		||||
        /// </para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// <param name="parameters">参数</param>
 | 
			
		||||
        /// <exception cref="TimeoutException">调用超时</exception>
 | 
			
		||||
        /// <exception cref="RpcInvokeException">调用内部异常</exception>
 | 
			
		||||
        /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception>
 | 
			
		||||
        /// <exception cref="Exception">其他异常</exception>
 | 
			
		||||
        Task InvokeAsync(string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters);
 | 
			
		||||
 | 
			
		||||
@@ -53,7 +52,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// <param name="parameters">参数</param>
 | 
			
		||||
        /// <exception cref="TimeoutException">调用超时</exception>
 | 
			
		||||
        /// <exception cref="RpcInvokeException">调用内部异常</exception>
 | 
			
		||||
        /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception>
 | 
			
		||||
        /// <exception cref="Exception">其他异常</exception>
 | 
			
		||||
        /// <returns>返回值</returns>
 | 
			
		||||
        Task<object> InvokeAsync(Type returnType, string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters);
 | 
			
		||||
@@ -67,7 +65,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// <param name="parameters">参数</param>
 | 
			
		||||
        /// <exception cref="TimeoutException">调用超时</exception>
 | 
			
		||||
        /// <exception cref="RpcInvokeException">调用内部异常</exception>
 | 
			
		||||
        /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception>
 | 
			
		||||
        /// <exception cref="Exception">其他异常</exception>
 | 
			
		||||
        void Invoke(string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters);
 | 
			
		||||
 | 
			
		||||
@@ -81,7 +78,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// <param name="parameters">参数</param>
 | 
			
		||||
        /// <exception cref="TimeoutException">调用超时</exception>
 | 
			
		||||
        /// <exception cref="RpcInvokeException">调用内部异常</exception>
 | 
			
		||||
        /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception>
 | 
			
		||||
        /// <exception cref="Exception">其他异常</exception>
 | 
			
		||||
        /// <returns>返回值</returns>
 | 
			
		||||
        object Invoke(Type returnType, string targetId, string invokeKey, IInvokeOption invokeOption, params object[] parameters);
 | 
			
		||||
@@ -96,7 +92,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// <param name="types"></param>
 | 
			
		||||
        /// <exception cref="TimeoutException">调用超时</exception>
 | 
			
		||||
        /// <exception cref="RpcInvokeException">调用内部异常</exception>
 | 
			
		||||
        /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception>
 | 
			
		||||
        /// <exception cref="Exception">其他异常</exception>
 | 
			
		||||
        void Invoke(string targetId, string invokeKey, IInvokeOption invokeOption, ref object[] parameters, Type[] types);
 | 
			
		||||
 | 
			
		||||
@@ -111,7 +106,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// <param name="types"></param>
 | 
			
		||||
        /// <exception cref="TimeoutException">调用超时</exception>
 | 
			
		||||
        /// <exception cref="RpcInvokeException">调用内部异常</exception>
 | 
			
		||||
        /// <exception cref="ClientNotFindException">没有找到Id对应的客户端</exception>
 | 
			
		||||
        /// <exception cref="Exception">其他异常</exception>
 | 
			
		||||
        /// <returns>返回值</returns>
 | 
			
		||||
        object Invoke(Type returnType, string targetId, string invokeKey, IInvokeOption invokeOption, ref object[] parameters, Type[] types);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,22 +21,12 @@ public abstract class BaseSerial : DependencyObject, ISerial
 | 
			
		||||
    /// 同步根。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected readonly object SyncRoot = new object();
 | 
			
		||||
    private int m_receiveBufferSize = 1024 * 10;
 | 
			
		||||
    private int m_sendBufferSize = 1024 * 10;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public virtual int SendBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => this.m_sendBufferSize;
 | 
			
		||||
        set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
    }
 | 
			
		||||
    public abstract int SendBufferSize { get; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public virtual int ReceiveBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => this.m_receiveBufferSize;
 | 
			
		||||
        set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
    }
 | 
			
		||||
    public abstract int ReceiveBufferSize { get; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public ILog Logger { get; set; }
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.IO.Ports;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Serial;
 | 
			
		||||
@@ -24,9 +23,14 @@ internal sealed class InternalSerialCore : SerialCore
 | 
			
		||||
public class SerialCore : IDisposable, ISender
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 初始缓存大小
 | 
			
		||||
    /// 最小缓存尺寸
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const int BufferSize = 1024 * 10;
 | 
			
		||||
    public int MinBufferSize { get; set; } = 1024 * 10;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 最大缓存尺寸
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public int MaxBufferSize { get; set; } = 1024 * 1024 * 10;
 | 
			
		||||
    #region 字段
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -35,14 +39,14 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    public readonly object SyncRoot = new object();
 | 
			
		||||
 | 
			
		||||
    private long m_bufferRate;
 | 
			
		||||
    private bool m_disposedValue;
 | 
			
		||||
    private SpinLock m_lock;
 | 
			
		||||
    private bool m_online => MainSerialPort?.IsOpen == true;
 | 
			
		||||
    private int m_receiveBufferSize = BufferSize;
 | 
			
		||||
    private bool m_online => m_serialPort?.IsOpen == true;
 | 
			
		||||
    private int m_receiveBufferSize = 1024 * 10;
 | 
			
		||||
    private ValueCounter m_receiveCounter;
 | 
			
		||||
    private int m_sendBufferSize = BufferSize;
 | 
			
		||||
    private int m_sendBufferSize = 1024 * 10;
 | 
			
		||||
    private ValueCounter m_sendCounter;
 | 
			
		||||
    private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
    private readonly EasyLock m_semaphoreForSend = new EasyLock();
 | 
			
		||||
    private SerialPort m_serialPort;
 | 
			
		||||
 | 
			
		||||
    #endregion 字段
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -50,7 +54,6 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public SerialCore()
 | 
			
		||||
    {
 | 
			
		||||
        this.m_lock = new SpinLock(Debugger.IsAttached);
 | 
			
		||||
        this.m_receiveCounter = new ValueCounter
 | 
			
		||||
        {
 | 
			
		||||
            Period = TimeSpan.FromSeconds(1),
 | 
			
		||||
@@ -69,7 +72,7 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    ~SerialCore()
 | 
			
		||||
    {
 | 
			
		||||
        this.Dispose(disposing: false);
 | 
			
		||||
        this.SafeDispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -100,19 +103,11 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    public Action<SerialCore, ByteBlock> OnReceived { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收缓存池(可以设定初始值,运行时的值会根据流速自动调整)
 | 
			
		||||
    /// 接收缓存池,运行时的值会根据流速自动调整
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public int ReceiveBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => this.m_receiveBufferSize;
 | 
			
		||||
        set
 | 
			
		||||
        {
 | 
			
		||||
            this.m_receiveBufferSize = value;
 | 
			
		||||
            if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
 | 
			
		||||
            {
 | 
			
		||||
                this.MainSerialPort.ReadBufferSize = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -121,19 +116,11 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    public ValueCounter ReceiveCounter { get => this.m_receiveCounter; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 发送缓存池(可以设定初始值,运行时的值会根据流速自动调整)
 | 
			
		||||
    /// 发送缓存池,运行时的值会根据流速自动调整
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public int SendBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => this.m_sendBufferSize;
 | 
			
		||||
        set
 | 
			
		||||
        {
 | 
			
		||||
            this.m_sendBufferSize = value;
 | 
			
		||||
            if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
 | 
			
		||||
            {
 | 
			
		||||
                this.MainSerialPort.WriteBufferSize = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -144,7 +131,7 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// SerialPort
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public SerialPort MainSerialPort { get; private set; }
 | 
			
		||||
    public SerialPort MainSerialPort { get => this.m_serialPort; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -155,11 +142,12 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
        var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
 | 
			
		||||
        this.UserToken = byteBlock;
 | 
			
		||||
        byteBlock.SetLength(0);
 | 
			
		||||
        if (this.MainSerialPort.BytesToRead > 0)
 | 
			
		||||
        if (this.m_serialPort.BytesToRead > 0)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_bufferRate += 2;
 | 
			
		||||
            this.ProcessReceived();
 | 
			
		||||
        }
 | 
			
		||||
        MainSerialPort.DataReceived += MainSerialPort_DataReceived;
 | 
			
		||||
        m_serialPort.DataReceived += MainSerialPort_DataReceived;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void MainSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
 | 
			
		||||
@@ -171,7 +159,7 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            this.PrivateBreakOut(false, ex.Message);
 | 
			
		||||
            this.PrivateBreakOut(false, ex.ToString());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -189,12 +177,12 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void Dispose()
 | 
			
		||||
    {
 | 
			
		||||
        this.Dispose(disposing: true);
 | 
			
		||||
        GC.SuppressFinalize(this);
 | 
			
		||||
        UserToken.SafeDispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 重置环境,并设置新的<see cref="MainSerialPort"/>。
 | 
			
		||||
    /// 重置环境,并设置新的<see cref="m_serialPort"/>。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="socket"></param>
 | 
			
		||||
    public virtual void Reset(SerialPort socket)
 | 
			
		||||
@@ -209,7 +197,7 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
            throw new Exception("新的SerialPort必须在连接状态。");
 | 
			
		||||
        }
 | 
			
		||||
        this.Reset();
 | 
			
		||||
        this.MainSerialPort = socket;
 | 
			
		||||
        this.m_serialPort = socket;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -219,14 +207,24 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    {
 | 
			
		||||
        this.m_receiveCounter.Reset();
 | 
			
		||||
        this.m_sendCounter.Reset();
 | 
			
		||||
        this.MainSerialPort = null;
 | 
			
		||||
        this.m_serialPort = null;
 | 
			
		||||
        this.OnReceived = null;
 | 
			
		||||
        this.OnBreakOut = null;
 | 
			
		||||
        this.UserToken = null;
 | 
			
		||||
        this.m_bufferRate = 1;
 | 
			
		||||
        this.m_lock = new SpinLock();
 | 
			
		||||
        this.m_receiveBufferSize = BufferSize;
 | 
			
		||||
        this.m_sendBufferSize = BufferSize;
 | 
			
		||||
        this.m_receiveBufferSize = this.MinBufferSize;
 | 
			
		||||
        this.m_sendBufferSize = this.MinBufferSize;
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 判断,当不在连接状态时触发异常。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <exception cref="NotConnectedException"></exception>
 | 
			
		||||
    protected void ThrowIfNotConnected()
 | 
			
		||||
    {
 | 
			
		||||
        if (!this.m_online)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotConnectedException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -240,15 +238,15 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    /// <param name="length"></param>
 | 
			
		||||
    public virtual void Send(byte[] buffer, int offset, int length)
 | 
			
		||||
    {
 | 
			
		||||
        var lockTaken = false;
 | 
			
		||||
        this.ThrowIfNotConnected();
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            this.m_lock.Enter(ref lockTaken);
 | 
			
		||||
            this.MainSerialPort.Write(buffer, offset, length);
 | 
			
		||||
            this.m_semaphoreForSend.Wait();
 | 
			
		||||
            this.m_serialPort.Write(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            if (lockTaken) this.m_lock.Exit(false);
 | 
			
		||||
            this.m_semaphoreForSend.Release();
 | 
			
		||||
        }
 | 
			
		||||
        this.m_sendCounter.Increment(length);
 | 
			
		||||
    }
 | 
			
		||||
@@ -263,15 +261,16 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
    /// <exception cref="Exception"></exception>
 | 
			
		||||
    public virtual async Task SendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
    {
 | 
			
		||||
        this.ThrowIfNotConnected();
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            await this.m_semaphore.WaitAsync();
 | 
			
		||||
            await this.m_semaphoreForSend.WaitAsync();
 | 
			
		||||
 | 
			
		||||
            this.MainSerialPort.Write(buffer, offset, length);
 | 
			
		||||
            this.m_serialPort.Write(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            this.m_semaphore.Release();
 | 
			
		||||
            this.m_semaphoreForSend.Release();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.m_sendCounter.Increment(length);
 | 
			
		||||
@@ -287,22 +286,7 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
        this.OnBreakOut?.Invoke(this, manual, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 释放对象
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="disposing"></param>
 | 
			
		||||
    protected virtual void Dispose(bool disposing)
 | 
			
		||||
    {
 | 
			
		||||
        if (!this.m_disposedValue)
 | 
			
		||||
        {
 | 
			
		||||
            if (disposing)
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.m_disposedValue = true;
 | 
			
		||||
        }
 | 
			
		||||
        UserToken.SafeDispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 当发生异常的时候
 | 
			
		||||
@@ -341,12 +325,20 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
 | 
			
		||||
    private void OnReceivePeriod(long value)
 | 
			
		||||
    {
 | 
			
		||||
        this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value);
 | 
			
		||||
        this.m_receiveBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize);
 | 
			
		||||
        if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
 | 
			
		||||
        {
 | 
			
		||||
            this.MainSerialPort.ReadBufferSize = this.m_receiveBufferSize;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void OnSendPeriod(long value)
 | 
			
		||||
    {
 | 
			
		||||
        this.SendBufferSize = TouchSocketUtility.HitBufferLength(value);
 | 
			
		||||
        this.m_sendBufferSize = Math.Max(TouchSocketUtility.HitBufferLength(value), this.MinBufferSize);
 | 
			
		||||
        if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
 | 
			
		||||
        {
 | 
			
		||||
            this.MainSerialPort.WriteBufferSize = this.m_sendBufferSize;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void PrivateBreakOut(bool manual, string msg)
 | 
			
		||||
@@ -367,21 +359,21 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
            UserToken?.SafeDispose();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (MainSerialPort.BytesToRead > 0)
 | 
			
		||||
        if (m_serialPort.BytesToRead > 0)
 | 
			
		||||
        {
 | 
			
		||||
            var byteBlock = UserToken;
 | 
			
		||||
            byte[] buffer = BytePool.Default.Rent(MainSerialPort.BytesToRead);
 | 
			
		||||
            int num = MainSerialPort.Read(buffer, 0, MainSerialPort.BytesToRead);
 | 
			
		||||
            byte[] buffer = BytePool.Default.Rent(m_serialPort.BytesToRead);
 | 
			
		||||
            int num = m_serialPort.Read(buffer, 0, m_serialPort.BytesToRead);
 | 
			
		||||
            byteBlock.Write(buffer, 0, num);
 | 
			
		||||
            byteBlock.SetLength(num);
 | 
			
		||||
            this.HandleBuffer(byteBlock);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
 | 
			
		||||
                var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, this.MaxBufferSize));
 | 
			
		||||
                newByteBlock.SetLength(0);
 | 
			
		||||
                UserToken = newByteBlock;
 | 
			
		||||
 | 
			
		||||
                if (MainSerialPort.BytesToRead > 0)
 | 
			
		||||
                if (m_serialPort.BytesToRead > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    this.m_bufferRate += 2;
 | 
			
		||||
                    this.ProcessReceived();
 | 
			
		||||
@@ -389,7 +381,7 @@ public class SerialCore : IDisposable, ISender
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                this.PrivateBreakOut(false, ex.Message);
 | 
			
		||||
                this.PrivateBreakOut(false, ex.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
 | 
			
		||||
    private DelaySender m_delaySender;
 | 
			
		||||
    private bool m_online => MainSerialPort?.IsOpen == true;
 | 
			
		||||
    private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
    private readonly EasyLock m_semaphore = new();
 | 
			
		||||
    private readonly InternalSerialCore m_serialCore;
 | 
			
		||||
    #endregion 变量
 | 
			
		||||
 | 
			
		||||
@@ -204,10 +204,10 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    #region 属性
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public DateTime LastReceivedTime => this.GetTcpCore().ReceiveCounter.LastIncrement;
 | 
			
		||||
    public DateTime LastReceivedTime => this.GetSerialCore().ReceiveCounter.LastIncrement;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public DateTime LastSendTime => this.GetTcpCore().SendCounter.LastIncrement;
 | 
			
		||||
    public DateTime LastSendTime => this.GetSerialCore().SendCounter.LastIncrement;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public IContainer Container { get; private set; }
 | 
			
		||||
@@ -255,7 +255,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
            {
 | 
			
		||||
                Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, msg));
 | 
			
		||||
                this.MainSerialPort.TryClose();
 | 
			
		||||
                this.BreakOut(default, true, msg);
 | 
			
		||||
                this.BreakOut(true, msg);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -272,7 +272,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
            if (this.m_online)
 | 
			
		||||
            {
 | 
			
		||||
                Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
 | 
			
		||||
                this.BreakOut(default, true, $"{nameof(Dispose)}主动断开");
 | 
			
		||||
                this.BreakOut(true, $"{nameof(Dispose)}主动断开");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        base.Dispose(disposing);
 | 
			
		||||
@@ -321,7 +321,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
 | 
			
		||||
    private void BeginReceive()
 | 
			
		||||
    {
 | 
			
		||||
        this.GetTcpCore().BeginIocpReceive();
 | 
			
		||||
        this.GetSerialCore().BeginIocpReceive();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -361,7 +361,16 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    private void BreakOut(SerialCore core, bool manual, string msg)
 | 
			
		||||
    private void SerialCoreBreakOut(SerialCore core, bool manual, string msg)
 | 
			
		||||
    {
 | 
			
		||||
        this.BreakOut(manual, msg);
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// BreakOut。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="manual"></param>
 | 
			
		||||
    /// <param name="msg"></param>
 | 
			
		||||
    protected void BreakOut(bool manual, string msg)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this.SyncRoot)
 | 
			
		||||
        {
 | 
			
		||||
@@ -375,32 +384,22 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private SerialCore GetTcpCore()
 | 
			
		||||
    private SerialCore GetSerialCore()
 | 
			
		||||
    {
 | 
			
		||||
        this.ThrowIfDisposed();
 | 
			
		||||
        return this.m_serialCore ?? throw new ObjectDisposedException(this.GetType().Name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override int ReceiveBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => this.GetTcpCore().ReceiveBufferSize;
 | 
			
		||||
        set
 | 
			
		||||
        {
 | 
			
		||||
            this.GetTcpCore().ReceiveBufferSize = value;
 | 
			
		||||
        }
 | 
			
		||||
        get => this.GetSerialCore().ReceiveBufferSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override int SendBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => this.GetTcpCore().SendBufferSize;
 | 
			
		||||
        set
 | 
			
		||||
        {
 | 
			
		||||
            this.GetTcpCore().SendBufferSize = value;
 | 
			
		||||
        }
 | 
			
		||||
        get => this.GetSerialCore().SendBufferSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -728,7 +727,12 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    {
 | 
			
		||||
        if (this.SendingData(buffer, offset, length).GetFalseAwaitResult())
 | 
			
		||||
        {
 | 
			
		||||
            this.GetTcpCore().Send(buffer, offset, length);
 | 
			
		||||
            if (this.m_delaySender != null)
 | 
			
		||||
            {
 | 
			
		||||
                this.m_delaySender.Send(new QueueDataBytes(buffer, offset, length));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.GetSerialCore().Send(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -737,7 +741,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    {
 | 
			
		||||
        if (await this.SendingData(buffer, offset, length))
 | 
			
		||||
        {
 | 
			
		||||
            await this.GetTcpCore().SendAsync(buffer, offset, length);
 | 
			
		||||
            await this.GetSerialCore().SendAsync(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -769,8 +773,16 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        }
 | 
			
		||||
        this.m_serialCore.Reset(serialPort);
 | 
			
		||||
        this.m_serialCore.OnReceived = this.HandleReceived;
 | 
			
		||||
        this.m_serialCore.OnBreakOut = this.BreakOut;
 | 
			
		||||
        this.m_serialCore.OnBreakOut = this.SerialCoreBreakOut;
 | 
			
		||||
        if (this.Config.GetValue(TouchSocketConfigExtension.MinBufferSizeProperty) is int minValue)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_serialCore.MinBufferSize = minValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.Config.GetValue(TouchSocketConfigExtension.MaxBufferSizeProperty) is int maxValue)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_serialCore.MaxBufferSize = maxValue;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void HandleReceived(SerialCore core, ByteBlock byteBlock)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,22 +35,11 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected readonly object SyncRoot = new object();
 | 
			
		||||
 | 
			
		||||
        private int m_receiveBufferSize = 1024 * 10;
 | 
			
		||||
        private int m_sendBufferSize = 1024 * 10;
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public abstract int SendBufferSize { get; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual int SendBufferSize
 | 
			
		||||
        {
 | 
			
		||||
            get => this.m_sendBufferSize;
 | 
			
		||||
            set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual int ReceiveBufferSize
 | 
			
		||||
        {
 | 
			
		||||
            get => this.m_receiveBufferSize;
 | 
			
		||||
            set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
        }
 | 
			
		||||
        public abstract int ReceiveBufferSize { get; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public ILog Logger { get; set; }
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,10 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int DelayLength { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 队列长度
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int QueueCount => this.m_queueDatas.Count;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user