Compare commits
	
		
			100 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d324537b47 | ||
|   | d0c05685f7 | ||
|   | 1063c930b5 | ||
|   | 79cbd44366 | ||
|   | 7fdac1c5cb | ||
|   | 0c0cf72ebb | ||
|   | 8e2fe175ed | ||
|   | d1cff037c9 | ||
|   | fc88a2fafa | ||
|   | 45fcceb056 | ||
|   | 7043477038 | ||
|   | 7dd685cf54 | ||
|   | 5f5e4969c0 | ||
|   | 8a53fd19e9 | ||
|   | baf4714c36 | ||
|   | 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,8 +1,7 @@ | ||||
| <Project> | ||||
| 	<PropertyGroup> | ||||
| 		<Version>3.0.0.10</Version> | ||||
| 		<Version>3.0.0.28</Version> | ||||
| 		<LangVersion>latest</LangVersion> | ||||
| 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> | ||||
| 		<Authors>Diego</Authors> | ||||
| 		<Product>ThingsGateway</Product> | ||||
| 		<Copyright>© 2023-present Diego</Copyright> | ||||
|   | ||||
| @@ -32,7 +32,6 @@ internal class Program | ||||
|         AppDomain.CurrentDomain.UnhandledException += (sender, error) => | ||||
|         { | ||||
|         }; | ||||
|  | ||||
|         app.Run(); | ||||
|     } | ||||
| } | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<OutputType>WinExe</OutputType> | ||||
| 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> | ||||
| 		<ApplicationIcon>favicon.ico</ApplicationIcon> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| @@ -28,5 +29,18 @@ | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <Content Update="wwwroot\favicon.ico"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	  </Content> | ||||
| 	  <Content Update="wwwroot\favicon.png"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	  </Content> | ||||
| 	  <Content Update="wwwroot\index.html"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	  </Content> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB | 
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB | 
| @@ -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", | ||||
| @@ -207,19 +207,40 @@ public partial class MainLayout | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "Title": "GasCustom", | ||||
|     "Title": "HZW_QTJC_01", | ||||
|     "Children": [ | ||||
|       { | ||||
|         "Href": "/GasCustomSerial", | ||||
|         "Title": "GasCustomSerial" | ||||
|         "Href": "/HZW_QTJC_01Serial", | ||||
|         "Title": "HZW_QTJC_01Serial" | ||||
|       }, | ||||
|       { | ||||
|         "Href": "/GasCustomSerialOverTcp", | ||||
|         "Title": "GasCustomSerialOverTcp" | ||||
|         "Href": "/HZW_QTJC_01SerialOverTcp", | ||||
|         "Title": "HZW_QTJC_01SerialOverTcp" | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
|  | ||||
|   }, | ||||
|   { | ||||
|     "Title": "LQTCP", | ||||
|     "Children": [ | ||||
|       { | ||||
|         "Href": "/LQTCP", | ||||
|         "Title": "LQTCP" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "Title": "KELID2008", | ||||
|     "Children": [ | ||||
|       { | ||||
|         "Href": "/KELID2008", | ||||
|         "Title": "KELID2008" | ||||
|       }, | ||||
|       { | ||||
|         "Href": "/KELID2008OverTcp", | ||||
|         "Title": "KELID2008OverTcp" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
| ] | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,18 +1,19 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk.Razor"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'"> | ||||
| 		<DefineConstants>Pro</DefineConstants> | ||||
| 	</PropertyGroup> | ||||
| 	<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'"> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro' AND '$(Configuration)' == 'Debug'"> | ||||
|  | ||||
| 		<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor.cs" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor.cs" /> | ||||
| 		<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor" /> | ||||
| 		<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Melsec\ThingsGateway.Foundation.Adapter.Melsec.csproj" /> | ||||
|  | ||||
| 		 | ||||
| 		 | ||||
|  | ||||
| 		<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor.cs" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor.cs" /> | ||||
| 		<Content Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor" /> | ||||
| 		<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.AllenBradleyCip\ThingsGateway.Foundation.Adapter.AllenBradleyCip.csproj" /> | ||||
| @@ -46,25 +47,44 @@ | ||||
| 		<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.HZW_QTJC_01\ThingsGateway.Foundation.Adapter.HZW_QTJC_01.csproj" /> | ||||
|  | ||||
|  | ||||
| 		 | ||||
|  | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro' "> | ||||
| 		<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.LQTCP\Page\LQTCPDebugPage.razor.cs" Link="Pages\LQTCP\LQTCPDebugPage.razor.cs" /> | ||||
| 	<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.LQTCP\Page\LQTCPDebugPage.razor" Link="Pages\LQTCP\LQTCPDebugPage.razor" /> | ||||
| 	<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.LQTCP\ThingsGateway.Foundation.Adapter.LQTCP.csproj" /> | ||||
|  | ||||
|  | ||||
| 	<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008DebugPage.razor.cs" Link="Pages\KELID2008\KELID2008DebugPage.razor.cs" /> | ||||
| 	<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008OverTcpDebugPage.razor.cs" Link="Pages\KELID2008\KELID2008OverTcpDebugPage.razor.cs" /> | ||||
| 	<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008DebugPage.razor" Link="Pages\KELID2008\KELID2008DebugPage.razor" /> | ||||
| 	<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008OverTcpDebugPage.razor" Link="Pages\KELID2008\KELID2008OverTcpDebugPage.razor" /> | ||||
| 	<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.KELID2008\ThingsGateway.Foundation.Adapter.KELID2008.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007DebugPage.razor.cs" /> | ||||
|  | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\MqttRpcNameVaueWithId.cs" Link="Pages\Mqtt\MqttRpcNameVaueWithId.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor.cs" Link="Pages\Mqtt\MqttClientDebugPage.razor.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor.cs" Link="Pages\Mqtt\MqttClientPage.razor.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\PrivateLogger.cs" Link="Pages\Mqtt\PrivateLogger.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClient.cs" Link="Pages\Mqtt\MqttRpcClient.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.cs" /> | ||||
| 		<Compile Include="..\..\Web\ThingsGateway.Gateway.Application\Workers\ManageGateway\MqttLoggerExtensions.cs" Link="Pages\Mqtt\MqttLoggerExtensions.cs" /> | ||||
| 		<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor" Link="Pages\Mqtt\MqttClientDebugPage.razor" /> | ||||
| 		<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor" Link="Pages\Mqtt\MqttClientPage.razor" /> | ||||
| 		<PackageReference Include="MQTTnet" Version="4.3.1.873" /> | ||||
| 		 | ||||
| 		 | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007DebugPage.razor.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" /> | ||||
|  | ||||
| 		 | ||||
|  | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuDebugPage.razor.cs" /> | ||||
| 		<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor" Link="Pages\Modbus\ModbusRtuDebugPage.razor" /> | ||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor.cs" /> | ||||
| @@ -115,38 +135,25 @@ | ||||
| 	</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> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<Content Update="wwwroot\**"> | ||||
| 			<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 		</Content> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor" Link="Pages\Mqtt\MqttClientDebugPage.razor" /> | ||||
| 	  <Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor" Link="Pages\Mqtt\MqttClientPage.razor" /> | ||||
| 		<PackageReference Include="MQTTnet" Version="4.3.1.873" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|   | ||||
|  | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -0,0 +1,16 @@ | ||||
| #region copyright | ||||
| //------------------------------------------------------------------------------ | ||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||
| //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||
| //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||
| //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||
| //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||
| //  QQ群:605534569 | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| global using System; | ||||
|  | ||||
| global using System.Windows.Forms; | ||||
|  | ||||
							
								
								
									
										78
									
								
								framework/Demo/ThingsGateway.Foundation.Demo.Winform/MainFrom.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,78 @@ | ||||
| #region copyright | ||||
| //------------------------------------------------------------------------------ | ||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||
| //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||
| //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||
| //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||
| //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||
| //  QQ群:605534569 | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
|  | ||||
| using System.Drawing; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Demo.Winform | ||||
| { | ||||
|     partial class MainFrom | ||||
|     { | ||||
|         /// <summary> | ||||
|         ///  Required designer variable. | ||||
|         /// </summary> | ||||
|         private System.ComponentModel.IContainer components = null; | ||||
|  | ||||
|         /// <summary> | ||||
|         ///  Clean up any resources being used. | ||||
|         /// </summary> | ||||
|         /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             if (disposing && (components != null)) | ||||
|             { | ||||
|                 components.Dispose(); | ||||
|             } | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         #region Windows Form Designer generated code | ||||
|  | ||||
|         /// <summary> | ||||
|         ///  Required method for Designer support - do not modify | ||||
|         ///  the contents of this method with the code editor. | ||||
|         /// </summary> | ||||
|         private void InitializeComponent() | ||||
|         { | ||||
|             System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainFrom)); | ||||
|             blazorWebView1 = new Microsoft.AspNetCore.Components.WebView.WindowsForms.BlazorWebView(); | ||||
|             SuspendLayout(); | ||||
|             //  | ||||
|             // blazorWebView1 | ||||
|             //  | ||||
|             blazorWebView1.Dock = DockStyle.Fill; | ||||
|             blazorWebView1.Location = new Point(0, 0); | ||||
|             blazorWebView1.Margin = new Padding(4); | ||||
|             blazorWebView1.Name = "blazorWebView1"; | ||||
|             blazorWebView1.Size = new Size(1029, 529); | ||||
|             blazorWebView1.TabIndex = 0; | ||||
|             blazorWebView1.Text = "blazorWebView1"; | ||||
|             //  | ||||
|             // MainFrom | ||||
|             //  | ||||
|             AutoScaleDimensions = new SizeF(9F, 20F); | ||||
|             AutoScaleMode = AutoScaleMode.Font; | ||||
|             ClientSize = new Size(1029, 529); | ||||
|             Controls.Add(blazorWebView1); | ||||
|             Icon = (Icon)resources.GetObject("$this.Icon"); | ||||
|             Margin = new Padding(4); | ||||
|             Name = "MainFrom"; | ||||
|             Text = "Form1"; | ||||
|             FormClosed += MainFrom_FormClosed; | ||||
|             ResumeLayout(false); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         private Microsoft.AspNetCore.Components.WebView.WindowsForms.BlazorWebView blazorWebView1; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,41 @@ | ||||
| #region copyright | ||||
| //------------------------------------------------------------------------------ | ||||
| //  <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>Ϊȫ<CEAA>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD> | ||||
| //  <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4>룩<EFBFBD><EBA3A9><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><DFB1><EFBFBD>Diego<67><6F><EFBFBD><EFBFBD> | ||||
| //  Դ<><D4B4><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Э<EFBFBD><D0AD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>ֿ<EFBFBD><D6BF>Ŀ<EFBFBD>ԴЭ<D4B4>鼰<EFBFBD><E9BCB0><EFBFBD><EFBFBD>Э<EFBFBD><D0AD> | ||||
| //  GiteeԴ<65><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway | ||||
| //  GithubԴ<62><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway | ||||
| //  ʹ<><CAB9><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ | ||||
| //  QQȺ<51><C8BA>605534569 | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| using Microsoft.AspNetCore.Components.WebView.WindowsForms; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
|  | ||||
| using ThingsGateway.Components; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Demo.Winform | ||||
| { | ||||
|     public partial class MainFrom : Form | ||||
|     { | ||||
|         public MainFrom() | ||||
|         { | ||||
|             InitializeComponent(); | ||||
|  | ||||
|             var services = new ServiceCollection(); | ||||
|             services.AddWindowsFormsBlazorWebView(); | ||||
|             services.ThingsGatewayComponentsConfigureServices(); | ||||
|  | ||||
|             blazorWebView1.HostPage = "wwwroot/index.html"; | ||||
|             blazorWebView1.Services = services.BuildServiceProvider(); | ||||
|             this.Text = "ThingsGateway.Foundation.Demo"; | ||||
|             blazorWebView1.RootComponents.Add<ThingsGateway.Foundation.Demo.App>("#app"); | ||||
|         } | ||||
|  | ||||
|         private void MainFrom_FormClosed(object sender, FormClosedEventArgs e) | ||||
|         { | ||||
|             Application.Exit(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,197 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <root> | ||||
|   <!-- | ||||
|     Microsoft ResX Schema  | ||||
|  | ||||
|     Version 2.0 | ||||
|  | ||||
|     The primary goals of this format is to allow a simple XML format | ||||
|     that is mostly human readable. The generation and parsing of the | ||||
|     various data types are done through the TypeConverter classes | ||||
|     associated with the data types. | ||||
|  | ||||
|     Example: | ||||
|  | ||||
|     ... ado.net/XML headers & schema ... | ||||
|     <resheader name="resmimetype">text/microsoft-resx</resheader> | ||||
|     <resheader name="version">2.0</resheader> | ||||
|     <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | ||||
|     <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | ||||
|     <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | ||||
|     <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | ||||
|     <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | ||||
|         <value>[base64 mime encoded serialized .NET Framework object]</value> | ||||
|     </data> | ||||
|     <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||||
|         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | ||||
|         <comment>This is a comment</comment> | ||||
|     </data> | ||||
|  | ||||
|     There are any number of "resheader" rows that contain simple | ||||
|     name/value pairs. | ||||
|  | ||||
|     Each data row contains a name, and value. The row also contains a | ||||
|     type or mimetype. Type corresponds to a .NET class that support | ||||
|     text/value conversion through the TypeConverter architecture. | ||||
|     Classes that don't support this are serialized and stored with the | ||||
|     mimetype set. | ||||
|  | ||||
|     The mimetype is used for serialized objects, and tells the | ||||
|     ResXResourceReader how to depersist the object. This is currently not | ||||
|     extensible. For a given mimetype the value must be set accordingly: | ||||
|  | ||||
|     Note - application/x-microsoft.net.object.binary.base64 is the format | ||||
|     that the ResXResourceWriter will generate, however the reader can | ||||
|     read any of the formats listed below. | ||||
|  | ||||
|     mimetype: application/x-microsoft.net.object.binary.base64 | ||||
|     value   : The object must be serialized with | ||||
|             : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | ||||
|             : and then encoded with base64 encoding. | ||||
|      | ||||
|     mimetype: application/x-microsoft.net.object.soap.base64 | ||||
|     value   : The object must be serialized with | ||||
|             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | ||||
|             : and then encoded with base64 encoding. | ||||
|  | ||||
|     mimetype: application/x-microsoft.net.object.bytearray.base64 | ||||
|     value   : The object must be serialized into a byte array | ||||
|             : using a System.ComponentModel.TypeConverter | ||||
|             : and then encoded with base64 encoding. | ||||
|     --> | ||||
|   <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | ||||
|     <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | ||||
|     <xsd:element name="root" msdata:IsDataSet="true"> | ||||
|       <xsd:complexType> | ||||
|         <xsd:choice maxOccurs="unbounded"> | ||||
|           <xsd:element name="metadata"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:sequence> | ||||
|                 <xsd:element name="value" type="xsd:string" minOccurs="0" /> | ||||
|               </xsd:sequence> | ||||
|               <xsd:attribute name="name" use="required" type="xsd:string" /> | ||||
|               <xsd:attribute name="type" type="xsd:string" /> | ||||
|               <xsd:attribute name="mimetype" type="xsd:string" /> | ||||
|               <xsd:attribute ref="xml:space" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|           <xsd:element name="assembly"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:attribute name="alias" type="xsd:string" /> | ||||
|               <xsd:attribute name="name" type="xsd:string" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|           <xsd:element name="data"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:sequence> | ||||
|                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||||
|                 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | ||||
|               </xsd:sequence> | ||||
|               <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | ||||
|               <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | ||||
|               <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | ||||
|               <xsd:attribute ref="xml:space" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|           <xsd:element name="resheader"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:sequence> | ||||
|                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||||
|               </xsd:sequence> | ||||
|               <xsd:attribute name="name" type="xsd:string" use="required" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|         </xsd:choice> | ||||
|       </xsd:complexType> | ||||
|     </xsd:element> | ||||
|   </xsd:schema> | ||||
|   <resheader name="resmimetype"> | ||||
|     <value>text/microsoft-resx</value> | ||||
|   </resheader> | ||||
|   <resheader name="version"> | ||||
|     <value>2.0</value> | ||||
|   </resheader> | ||||
|   <resheader name="reader"> | ||||
|     <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
|   </resheader> | ||||
|   <resheader name="writer"> | ||||
|     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
|   </resheader> | ||||
|   <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | ||||
|   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||||
|     <value> | ||||
|         AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAwo82AMKPNgvCjzYkwo82JsKPNifCjzYqwo82IcKPNgLCjzYAAAAAAAAA | ||||
|         AAAAAAAAAAAAAMKPNgDCjzYBwo82HsKPNknCjzZewo82QcKPNhLCjzYAwo82AAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCjzYAwo82S8KPNtPCjzbiwo8258KPNuDCjzatwo82EsKP | ||||
|         NgAAAAAAAAAAAAAAAADCjzYAwo82BsKPNmvCjzbbwo826MKPNtvCjzbhwo82vcKPNmDCjzYywo82AAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMKPNgDCjzYPwo82O8KPNs7Cjzb/wo82iMKP | ||||
|         Nh7CjzYCwo82AAAAAAAAAAAAwo82AMKPNgDCjzZnwo8298KPNsLCjzY6wo82GsKPNjTCjzbJwo82/8KP | ||||
|         NpTCjzYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMKPNgDCjzYIwo82vsKP | ||||
|         Nv/CjzZowo82AAAAAAAAAAAAAAAAAAAAAADCjzYAwo82JMKPNtnCjzbxwo82QcKPNgDCjzYAwo82AMKP | ||||
|         NpHCjzb/wo82lsKPNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwo82AMKP | ||||
|         NgjCjza9wo82/8KPNmjCjzYAAAAAAAAAAAAAAAAAwo82AMKPNgDCjzZ2wo82/8KPNrnCjzYKwo82AAAA | ||||
|         AADCjzYAwo82jcKPNv/CjzaWwo82AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AADCjzYAwo82CMKPNr3Cjzb/wo82aMKPNgAAAAAAAAAAAAAAAADCjzYAwo82CcKPNrrCjzb/wo82fcKP | ||||
|         NgDCjzYAAAAAAMKPNgDCjzaLwo82/8KPNpbCjzYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAMKPNgDCjzYIwo82vMKPNv/CjzZpwo82AAAAAAAAAAAAAAAAAMKPNgDCjzYfwo8238KP | ||||
|         Nv3CjzZRwo82AMKPNgDCjzYBwo82B8KPNpnCjzb/wo82psKPNgrCjzYAwo82AAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAwo82AMKPNgjCjza8wo82/8KPNmnCjzYAAAAAAAAAAAAAAAAAwo82AMKP | ||||
|         NjbCjzbxwo829sKPNj7CjzYAwo82AMKPNiPCjzaywo827cKPNv/Cjzbywo82qMKPNhPCjzYAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCjzYAwo82CMKPNrvCjzb/wo82acKPNgAAAAAAAAAAAAAA | ||||
|         AADCjzYAwo82P8KPNvfCjzbzwo82OcKPNgDCjzYAwo82D8KPNlnCjzZiwo82X8KPNmDCjzZRwo82CcKP | ||||
|         NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMKPNgDCjzYHwo82usKPNv/CjzZpwo82AAAA | ||||
|         AAAAAAAAAAAAAMKPNgDCjzY+wo829sKPNvTCjzY8wo82AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwo82AMKPNgfCjza6wo82/8KP | ||||
|         NmnCjzYAAAAAAAAAAAAAAAAAwo82AMKPNirCjzbpwo82+MKPNkDCjzYAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCjzYAwo82B8KP | ||||
|         NrnCjzb/wo82acKPNgAAAAAAAAAAAAAAAADCjzYAwo82FcKPNtLCjzb/wo82VsKPNgAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwo82AMKPNgLCjzYTwo82BMKP | ||||
|         NgDCjzYHwo82t8KPNv/CjzZpwo82AMKPNgDCjzYMwo82E8KPNgDCjzYCwo82n8KPNv/CjzaEwo82AMKP | ||||
|         NgAAAAAAwo82AMKPNgDCjzZPwo82XcKPNgLCjzYAAAAAAAAAAAAAAAAAAAAAAAAAAADCjzYAwo82F8KP | ||||
|         NrTCjzY6wo82AMKPNgbCjza0wo82/8KPNmnCjzYAwo82AMKPNnPCjzaawo82A8KPNgDCjzZOwo82+MKP | ||||
|         NsbCjzYRwo82AAAAAADCjzYAwo82DcKPNsLCjzagwo82AMKPNgAAAAAAAAAAAAAAAAAAAAAAAAAAAMKP | ||||
|         NgDCjzYPwo82ysKPNpPCjzYBwo82BcKPNrHCjzb/wo82acKPNgDCjzYUwo82zMKPNpPCjzYAwo82AMKP | ||||
|         NgrCjzanwo82/MKPNmnCjzYAwo82AMKPNgDCjzZRwo8298KPNnbCjzYAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAwo82AMKPNgDCjzaawo827cKPNmHCjzYswo82vMKPNv/CjzaEwo82K8KPNoDCjzb5wo82ZMKP | ||||
|         NgAAAAAAwo82AMKPNi7CjzbWwo825sKPNlnCjzYdwo82SMKPNtTCjzb9wo82UsKPNgAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAwo82AMKPNmHCjzb3wo828cKPNt/Cjzbuwo8298KPNurCjzbjwo829MKP | ||||
|         NurCjzY6wo82AAAAAADCjzYAwo82AMKPNjfCjza8wo826cKPNtvCjzbewo82ycKPNs7CjzYvwo82AAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCjzYAwo82EsKPNj3CjzZAwo82QcKPNkDCjzY/wo82QMKP | ||||
|         NkDCjzY/wo82OMKPNgrCjzYAAAAAAAAAAADCjzYAwo82AMKPNg/CjzY5wo82SsKPNjDCjzYOwo82G8KP | ||||
|         NgXCjzYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||||
|         AAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////wH4H/8B8Af/AfAH/4f | ||||
|         hx/+H4cf/h8PH/4fDAf+HwwH/h8MB/4fD//+Hw///h8P/+IZD4/iGIcP4BGHH+ABwB/wAeAf8AHwH/// | ||||
|         //////////////////////////////////8= | ||||
| </value> | ||||
|   </data> | ||||
| </root> | ||||
| @@ -0,0 +1,19 @@ | ||||
| using System.Windows.Forms; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Demo.Winform | ||||
| { | ||||
|     internal static class Program | ||||
|     { | ||||
|         /// <summary> | ||||
|         ///  The main entry point for the application. | ||||
|         /// </summary> | ||||
|         [STAThread] | ||||
|         static void Main() | ||||
|         { | ||||
|             // To customize application configuration such as set high DPI settings or default font, | ||||
|             // see https://aka.ms/applicationconfiguration. | ||||
|             ApplicationConfiguration.Initialize(); | ||||
|             Application.Run(new MainFrom()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,47 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk.Razor"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<OutputType>WinExe</OutputType> | ||||
| 		<ApplicationIcon>favicon.ico</ApplicationIcon> | ||||
| 		<TargetFrameworks>net7.0-windows</TargetFrameworks> | ||||
| 		<UseWindowsForms>true</UseWindowsForms> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <None Remove="favicon.ico" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <Content Include="favicon.ico"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	    <ExcludeFromSingleFile>true</ExcludeFromSingleFile> | ||||
| 	    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> | ||||
| 	  </Content> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Microsoft.AspNetCore.Components.WebView.WindowsForms" Version="7.0.96" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\ThingsGateway.Foundation.Demo.Rcl\ThingsGateway.Foundation.Demo.Rcl.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <Content Update="wwwroot\favicon.ico"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	  </Content> | ||||
| 	  <Content Update="wwwroot\favicon.png"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	  </Content> | ||||
| 	  <Content Update="wwwroot\index.html"> | ||||
| 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| 	  </Content> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|  | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										
											BIN
										
									
								
								framework/Demo/ThingsGateway.Foundation.Demo.Winform/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.2 KiB | 
| After Width: | Height: | Size: 4.2 KiB | 
| After Width: | Height: | Size: 10 KiB | 
| @@ -0,0 +1,41 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" /> | ||||
|     <title>ThingsGateway.Foundation.Demo</title> | ||||
|     <base href="/" /> | ||||
|  | ||||
|     <link rel="icon" href="favicon.ico" type="image/x-icon"> | ||||
|  | ||||
|  | ||||
|     <link href="_content/Masa.Blazor/css/masa-blazor.min.css" rel="stylesheet" /> | ||||
|     <link href="_content/ThingsGateway.Components/css/materialdesign/v7.1.96/css/materialdesignicons.min.css" rel="stylesheet"> | ||||
|     <link href="_content/ThingsGateway.Components/css/material/icons.css" rel="stylesheet"> | ||||
|     <link href="_content/ThingsGateway.Components/css/fontawesome/v6.4.0/css/all.min.css" rel="stylesheet"> | ||||
|     <link href="_content/ThingsGateway.Components/style/custom.css" rel="stylesheet"> | ||||
|     <link href="_content/ThingsGateway.Components/prism/prism-material-dark-for-masa.css" rel="stylesheet"> | ||||
|     <link href="_content/ThingsGateway.Components/prism/prism-line-highlight.min.css" rel="stylesheet"> | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|     <div id="app"></div> | ||||
|  | ||||
|     <div id="blazor-error-ui"> | ||||
|         <span> | ||||
|             <environment include="Staging,Production"> | ||||
|                 An error has occurred. This application may no longer respond until reloaded. | ||||
|             </environment> | ||||
|             <environment include="Development"> | ||||
|                 An unhandled exception has occurred. See browser dev tools for details. | ||||
|             </environment> | ||||
|         </span> | ||||
|         <a href="" class="reload">Reload</a> | ||||
|         <a class="dismiss">🗙</a> | ||||
|     </div> | ||||
|  | ||||
|     <script src="_framework/blazor.webview.js" autostart="true"></script> | ||||
|     <script src="_content/ThingsGateway.Components/prism/prism.min.js"></script> | ||||
|     <script src="_content/BlazorComponent/js/blazor-component.js"></script> | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,6 +1,6 @@ | ||||
| <Project> | ||||
| 	<PropertyGroup> | ||||
| 		<Version>3.0.0.10</Version> | ||||
| 		<Version>3.0.0.28</Version> | ||||
| 		<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||||
| 		<LangVersion>latest</LangVersion> | ||||
| 		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks> | ||||
|   | ||||
| @@ -35,12 +35,7 @@ public class DataInfo | ||||
| } | ||||
| internal static class DLT645Helper | ||||
| { | ||||
|     internal static byte[] BytesAdd(this byte[] bytes, int value) | ||||
|     { | ||||
|         for (int index = 0; index < bytes.Length; ++index) | ||||
|             bytes[index] = (byte)(bytes[index] + value); | ||||
|         return bytes; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     internal static string Get2007ErrorMessage(byte buffer) | ||||
|     { | ||||
|   | ||||
| @@ -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() | ||||
|     { | ||||
|   | ||||
| @@ -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; } | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
| @@ -7,9 +7,8 @@ | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||
| 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.4.372.56" /> | ||||
| 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.56" /> | ||||
| 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.4.372.76" /> | ||||
| 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.76" /> | ||||
| 	</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; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -10,6 +10,8 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| using System.Text; | ||||
|  | ||||
| using ThingsGateway.Foundation.Extension.Generic; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Core; | ||||
| @@ -19,6 +21,10 @@ namespace ThingsGateway.Foundation.Core; | ||||
| /// </summary> | ||||
| public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDataHandlingAdapter<TRequest> where TRequest : class, IMessage | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 报文输出时采用字符串还是HexString | ||||
|     /// </summary> | ||||
|     public virtual bool IsHexData { get; set; } = true; | ||||
|     /// <inheritdoc cref="ReadWriteDevicesTcpDataHandleAdapter{TRequest}"/> | ||||
|     public ReadWriteDevicesTcpDataHandleAdapter() | ||||
|     { | ||||
| @@ -46,7 +52,7 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | ||||
|     { | ||||
|         //获取全部内容 | ||||
|         var allBytes = byteBlock.ToArray(0, byteBlock.Len); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 接收:{allBytes.ToHexString(' ')}"); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 接收:{(IsHexData ? allBytes.ToHexString(' ') : Encoding.UTF8.GetString(allBytes))}"); | ||||
|         //缓存/不缓存解析一样,因为游标已经归0 | ||||
|         { | ||||
|             request = Request; | ||||
| @@ -131,7 +137,7 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | ||||
|     /// <summary> | ||||
|     /// 发送方法,会重新建立<see cref="Request"/> | ||||
|     /// </summary> | ||||
|     protected void GoSend(byte[] item) | ||||
|     protected virtual void GoSend(byte[] item) | ||||
|     { | ||||
|         byte[] bytes; | ||||
|         if (IsSendPackCommand) | ||||
| @@ -141,12 +147,12 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | ||||
|         Request = GetInstance(); | ||||
|         Request.SendBytes = bytes; | ||||
|         GoSend(bytes, 0, bytes.Length); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}"); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{(IsHexData ? Request.SendBytes.ToHexString(' ') : Encoding.UTF8.GetString(Request.SendBytes))}"); | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// 发送方法,会重新建立<see cref="Request"/> | ||||
|     /// </summary> | ||||
|     protected async Task GoSendAsync(byte[] item) | ||||
|     protected virtual async Task GoSendAsync(byte[] item) | ||||
|     { | ||||
|         byte[] bytes; | ||||
|         if (IsSendPackCommand) | ||||
| @@ -156,7 +162,7 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | ||||
|         Request = GetInstance(); | ||||
|         Request.SendBytes = bytes; | ||||
|         await GoSendAsync(bytes, 0, bytes.Length); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}"); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{(IsHexData ? Request.SendBytes.ToHexString(' ') : Encoding.UTF8.GetString(Request.SendBytes))}"); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
| @@ -180,6 +186,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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -11,6 +11,7 @@ | ||||
| #endregion | ||||
|  | ||||
| using System.Net; | ||||
| using System.Text; | ||||
|  | ||||
| using ThingsGateway.Foundation.Extension.Generic; | ||||
|  | ||||
| @@ -21,6 +22,13 @@ namespace ThingsGateway.Foundation.Core; | ||||
| /// </summary> | ||||
| public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHandlingAdapter where TRequest : class, IMessage | ||||
| { | ||||
|  | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 报文输出时采用字符串还是HexString | ||||
|     /// </summary> | ||||
|     public virtual bool IsHexData { get; set; } = true; | ||||
|  | ||||
|     /// <inheritdoc cref="ReadWriteDevicesUdpDataHandleAdapter{TRequest}"/> | ||||
|     public ReadWriteDevicesUdpDataHandleAdapter() | ||||
|     { | ||||
| @@ -68,13 +76,13 @@ public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHa | ||||
|         Request = GetInstance(); | ||||
|         Request.SendBytes = bytes; | ||||
|         GoSend(endPoint, bytes, 0, bytes.Length); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}"); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{(IsHexData ? Request.SendBytes.ToHexString(' ') : Encoding.UTF8.GetString(Request.SendBytes))}"); | ||||
|     } | ||||
|     /// <inheritdoc/> | ||||
|     protected override void PreviewReceived(EndPoint remoteEndPoint, ByteBlock byteBlock) | ||||
|     { | ||||
|         var allBytes = byteBlock.ToArray(0, byteBlock.Len); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 接收:{allBytes.ToHexString(' ')}"); | ||||
|         Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 接收:{(IsHexData ? allBytes.ToHexString(' ') : Encoding.UTF8.GetString(allBytes))}"); | ||||
|  | ||||
|         if (Request?.SendBytes == null) | ||||
|         { | ||||
|   | ||||
| @@ -10,6 +10,8 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| #endregion | ||||
|  | ||||
| using System.Text; | ||||
|  | ||||
| using ThingsGateway.Foundation.Extension.Generic; | ||||
|  | ||||
| namespace ThingsGateway.Foundation.Core; | ||||
| @@ -17,6 +19,39 @@ namespace ThingsGateway.Foundation.Core; | ||||
| /// <inheritdoc/> | ||||
| public static class ByteExtensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 获取异或校验 | ||||
|     /// </summary> | ||||
|     /// <param name="data"></param> | ||||
|     /// <param name="left"></param> | ||||
|     /// <param name="right"></param> | ||||
|     /// <returns></returns> | ||||
|     public static byte[] GetAsciiXOR(this byte[] data, int left, int right) | ||||
|     { | ||||
|         int tmp = data[left]; | ||||
|         for (int i = left + 1; i < data.Length - right; i++) | ||||
|         { | ||||
|             tmp = (tmp ^ data[i]); | ||||
|         } | ||||
|  | ||||
|         byte[] fcs = new byte[2]; | ||||
|         fcs[0] = Encoding.ASCII.GetBytes(((byte)tmp).ToString("X2"))[0]; | ||||
|         fcs[1] = Encoding.ASCII.GetBytes(((byte)tmp).ToString("X2"))[1]; | ||||
|         return fcs; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 数组内容分别相加某个数字 | ||||
|     /// </summary> | ||||
|     /// <param name="bytes"></param> | ||||
|     /// <param name="value"></param> | ||||
|     /// <returns></returns> | ||||
|     public static byte[] BytesAdd(this byte[] bytes, int value) | ||||
|     { | ||||
|         for (int index = 0; index < bytes.Length; ++index) | ||||
|             bytes[index] = (byte)(bytes[index] + value); | ||||
|         return bytes; | ||||
|     } | ||||
|     /// <summary> | ||||
|     /// 获取byte数据类型的第offset位,是否为True<br /> | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -103,12 +103,12 @@ namespace ThingsGateway.Foundation.Core | ||||
|                 { | ||||
|                     return FilterResult.Cache; | ||||
|                 } | ||||
|                 if (!requestInfo.OnParsingStartCode(byteBlock.ToArray(byteBlock.Pos, this.StartCode.Length))) | ||||
|                 if (!requestInfo.OnParsingStartCode(byteBlock.ToArray(byteBlock.Pos + indexStart + 1 - this.StartCode.Length, this.StartCode.Length))) | ||||
|                 { | ||||
|                     byteBlock.Pos += this.StartCode.Length; | ||||
|                     byteBlock.Pos += indexStart; | ||||
|                     return FilterResult.GoOn; | ||||
|                 } | ||||
|                 byteBlock.Pos += this.StartCode.Length; | ||||
|                 byteBlock.Pos += indexStart + 1; | ||||
|                 request = requestInfo; | ||||
|  | ||||
|                 int len; | ||||
|   | ||||
| @@ -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); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||