Compare commits
	
		
			59 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 4cf35f7294 | ||
|   | 94c77d151b | ||
|   | 7f600e2b4b | ||
|   | c809d0ba87 | ||
|   | 50f038ec89 | ||
|   | 9199a255a2 | ||
|   | 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 | 
| @@ -1,8 +1,7 @@ | |||||||
| <Project> | <Project> | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<Version>3.0.0.22</Version> | 		<Version>3.0.1.0</Version> | ||||||
| 		<LangVersion>latest</LangVersion> | 		<LangVersion>latest</LangVersion> | ||||||
| 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> |  | ||||||
| 		<Authors>Diego</Authors> | 		<Authors>Diego</Authors> | ||||||
| 		<Product>ThingsGateway</Product> | 		<Product>ThingsGateway</Product> | ||||||
| 		<Copyright>© 2023-present Diego</Copyright> | 		<Copyright>© 2023-present Diego</Copyright> | ||||||
|   | |||||||
| @@ -32,7 +32,6 @@ internal class Program | |||||||
|         AppDomain.CurrentDomain.UnhandledException += (sender, error) => |         AppDomain.CurrentDomain.UnhandledException += (sender, error) => | ||||||
|         { |         { | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         app.Run(); |         app.Run(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -2,6 +2,7 @@ | |||||||
|  |  | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<OutputType>WinExe</OutputType> | 		<OutputType>WinExe</OutputType> | ||||||
|  | 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> | ||||||
| 		<ApplicationIcon>favicon.ico</ApplicationIcon> | 		<ApplicationIcon>favicon.ico</ApplicationIcon> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| @@ -28,5 +29,18 @@ | |||||||
| 	</ItemGroup> | 	</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> | </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 | 
| @@ -26,10 +26,10 @@ | |||||||
|         <MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@port /> |         <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 Class="ma-1" OnClick=@Connect Color="primary"> | ||||||
|             连接 |             启动 | ||||||
|         </MButton> |         </MButton> | ||||||
|         <MButton Class="ma-1" OnClick=@DisConnect Color="red"> |         <MButton Class="ma-1" OnClick=@DisConnect Color="red"> | ||||||
|             断开 |             停止 | ||||||
|         </MButton> |         </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> | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
| //  Դ<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 | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
| //  GithubԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
| //  ʹ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/ | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
| //  QQȺ<EFBFBD><EFBFBD>605534569 | //  QQ群:605534569 | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
| @@ -26,7 +26,7 @@ public partial class MainLayout | |||||||
| [ | [ | ||||||
|   { |   { | ||||||
|     "Href": "/index", |     "Href": "/index", | ||||||
|     "Title": "<EFBFBD><EFBFBD>ҳ" |     "Title": "首页" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "Title": "Modbus", |     "Title": "Modbus", | ||||||
| @@ -207,19 +207,40 @@ public partial class MainLayout | |||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "Title": "GasCustom", |     "Title": "HZW_QTJC_01", | ||||||
|     "Children": [ |     "Children": [ | ||||||
|       { |       { | ||||||
|         "Href": "/GasCustomSerial", |         "Href": "/HZW_QTJC_01Serial", | ||||||
|         "Title": "GasCustomSerial" |         "Title": "HZW_QTJC_01Serial" | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         "Href": "/GasCustomSerialOverTcp", |         "Href": "/HZW_QTJC_01SerialOverTcp", | ||||||
|         "Title": "GasCustomSerialOverTcp" |         "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"> | <Project Sdk="Microsoft.NET.Sdk.Razor"> | ||||||
|  |  | ||||||
|  | 	<PropertyGroup> | ||||||
|  | 		<TargetFrameworks>net6.0;net7.0</TargetFrameworks> | ||||||
|  | 	</PropertyGroup> | ||||||
|  |  | ||||||
| 	<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'"> | 	<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'"> | ||||||
| 		<DefineConstants>Pro</DefineConstants> | 		<DefineConstants>Pro</DefineConstants> | ||||||
| 	</PropertyGroup> | 	</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" /> | 		<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" /> | 		<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" /> | 		<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" /> | 		<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" /> | 		<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" /> | 		<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.AllenBradleyCip\ThingsGateway.Foundation.Adapter.AllenBradleyCip.csproj" /> | ||||||
| @@ -49,17 +50,36 @@ | |||||||
|  |  | ||||||
| 	</ItemGroup> | 	</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> | 	<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\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\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\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\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\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" /> | ||||||
| 		<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.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" /> | 		<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" /> | 		<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" /> | 		<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor" /> | ||||||
| @@ -115,7 +135,7 @@ | |||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
|  |  | ||||||
| 	<ItemGroup > | 	<ItemGroup> | ||||||
| 		<!--<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" /> | 		<!--<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" /> | ||||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="*" /> | 		<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="*" /> | ||||||
| 		<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCDA" Version="*" /> | 		<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCDA" Version="*" /> | ||||||
| @@ -128,24 +148,11 @@ | |||||||
| 		<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 > | 	<ItemGroup> | ||||||
| 		<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" /> | 		<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" /> | ||||||
| 	</ItemGroup> | 	</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> |  | ||||||
|   |   | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| #region copyright | #region copyright | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
| @@ -10,12 +10,7 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| #endregion | #endregion | ||||||
| 
 | 
 | ||||||
| namespace ThingsGateway.Foundation.Serial; | global using System; | ||||||
| 
 | 
 | ||||||
| /// <summary> | global using System.Windows.Forms; | ||||||
| /// 串口基接口 |  | ||||||
| /// </summary> |  | ||||||
| public interface ISerial : ISocket |  | ||||||
| { |  | ||||||
| 
 | 
 | ||||||
| } |  | ||||||
							
								
								
									
										77
									
								
								framework/Demo/ThingsGateway.Foundation.Demo.Winform/MainFrom.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,77 @@ | |||||||
|  | #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 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群: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,29 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | 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> | <Project> | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<Version>3.0.0.22</Version> | 		<Version>3.0.1.0</Version> | ||||||
| 		<GenerateDocumentationFile>True</GenerateDocumentationFile> | 		<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||||||
| 		<LangVersion>latest</LangVersion> | 		<LangVersion>latest</LangVersion> | ||||||
| 		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks> | 		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks> | ||||||
|   | |||||||
| @@ -35,12 +35,7 @@ public class DataInfo | |||||||
| } | } | ||||||
| internal static class DLT645Helper | 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) |     internal static string Get2007ErrorMessage(byte buffer) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -186,7 +186,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase | |||||||
|                 var item = commandResult.Content; |                 var item = commandResult.Content; | ||||||
|                 if (FrameTime != 0) |                 if (FrameTime != 0) | ||||||
|                     Thread.Sleep(FrameTime); |                     Thread.Sleep(FrameTime); | ||||||
|                 var WaitingClientEx = client.CreateWaitingClient(new() { ThrowBreakException = true }); |                 var WaitingClientEx = client.CreateWaitingClient(new() { }); | ||||||
|                 var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken); |                 var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken); | ||||||
|                 return (MessageBase)result.RequestInfo; |                 return (MessageBase)result.RequestInfo; | ||||||
|             } |             } | ||||||
| @@ -213,7 +213,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase | |||||||
|  |  | ||||||
|                 var item = commandResult.Content; |                 var item = commandResult.Content; | ||||||
|                 await Task.Delay(FrameTime, cancellationToken); |                 await Task.Delay(FrameTime, cancellationToken); | ||||||
|                 var WaitingClientEx = client.CreateWaitingClient(new() { ThrowBreakException = true }); |                 var WaitingClientEx = client.CreateWaitingClient(new() { }); | ||||||
|                 var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken); |                 var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken); | ||||||
|                 return (MessageBase)result.RequestInfo; |                 return (MessageBase)result.RequestInfo; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| #region copyright | #region copyright | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
| @@ -9,7 +8,6 @@ | |||||||
| //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
| //  QQ群:605534569 | //  QQ群:605534569 | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
| using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||||
| @@ -49,7 +47,7 @@ public class OPCUAClient : IDisposable | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 当前保存的变量名称列表 |     /// 当前保存的变量名称列表 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public List<string> Variables = new(); |     public List<List<string>> Variables = new(); | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 当前的变量名称/OPC变量节点 |     /// 当前的变量名称/OPC变量节点 | ||||||
| @@ -518,9 +516,9 @@ public class OPCUAClient : IDisposable | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 连接到服务器 |     /// 连接到服务器 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public async Task ConnectAsync() |     public async Task ConnectAsync(CancellationToken cancellationToken) | ||||||
|     { |     { | ||||||
|         await ConnectAsync(OPCNode.OPCUrl); |         await ConnectAsync(OPCNode.OPCUrl, cancellationToken); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -540,7 +538,7 @@ public class OPCUAClient : IDisposable | |||||||
|     /// Creates a new session. |     /// Creates a new session. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <returns>The new session object.</returns> |     /// <returns>The new session object.</returns> | ||||||
|     private async Task<ISession> ConnectAsync(string serverUrl) |     private async Task<ISession> ConnectAsync(string serverUrl, CancellationToken cancellationToken) | ||||||
|     { |     { | ||||||
|         PrivateDisconnect(); |         PrivateDisconnect(); | ||||||
|  |  | ||||||
| @@ -549,6 +547,7 @@ public class OPCUAClient : IDisposable | |||||||
|             throw new ArgumentNullException("未初始化配置"); |             throw new ArgumentNullException("未初始化配置"); | ||||||
|         } |         } | ||||||
|         var useSecurity = OPCNode?.IsUseSecurity ?? true; |         var useSecurity = OPCNode?.IsUseSecurity ?? true; | ||||||
|  |  | ||||||
|         EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(m_configuration, serverUrl, useSecurity, 10000); |         EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(m_configuration, serverUrl, useSecurity, 10000); | ||||||
|         EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); |         EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); | ||||||
|         ConfiguredEndpoint endpoint = new(null, endpointDescription, endpointConfiguration); |         ConfiguredEndpoint endpoint = new(null, endpointDescription, endpointConfiguration); | ||||||
| @@ -571,7 +570,8 @@ public class OPCUAClient : IDisposable | |||||||
|         (string.IsNullOrEmpty(OPCUAName)) ? m_configuration.ApplicationName : OPCUAName, |         (string.IsNullOrEmpty(OPCUAName)) ? m_configuration.ApplicationName : OPCUAName, | ||||||
|         60000, |         60000, | ||||||
|         userIdentity, |         userIdentity, | ||||||
|         Array.Empty<string>()); |         Array.Empty<string>(), cancellationToken | ||||||
|  |         ).ConfigureAwait(false); | ||||||
|         typeSystem = new ComplexTypeSystem(m_session); |         typeSystem = new ComplexTypeSystem(m_session); | ||||||
|  |  | ||||||
|         m_session.KeepAliveInterval = OPCNode.KeepAliveInterval == 0 ? 60000 : OPCNode.KeepAliveInterval; |         m_session.KeepAliveInterval = OPCNode.KeepAliveInterval == 0 ? 60000 : OPCNode.KeepAliveInterval; | ||||||
| @@ -584,7 +584,12 @@ public class OPCUAClient : IDisposable | |||||||
|  |  | ||||||
|         //如果是订阅模式,连接时添加订阅组 |         //如果是订阅模式,连接时添加订阅组 | ||||||
|         if (OPCNode.ActiveSubscribe) |         if (OPCNode.ActiveSubscribe) | ||||||
|             await AddSubscriptionAsync(Guid.NewGuid().ToString(), Variables.ToArray(), OPCNode.LoadType); |         { | ||||||
|  |             foreach (var item in Variables) | ||||||
|  |             { | ||||||
|  |                 await AddSubscriptionAsync(Guid.NewGuid().ToString(), item.ToArray(), OPCNode.LoadType); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return m_session; |         return m_session; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -741,7 +746,7 @@ public class OPCUAClient : IDisposable | |||||||
|         NodeId nodeToRead = new(nodeIdStr); |         NodeId nodeToRead = new(nodeIdStr); | ||||||
|         var node = (VariableNode)await m_session.ReadNodeAsync(nodeToRead, NodeClass.Variable, false, cancellationToken); |         var node = (VariableNode)await m_session.ReadNodeAsync(nodeToRead, NodeClass.Variable, false, cancellationToken); | ||||||
|         if (OPCNode.LoadType) |         if (OPCNode.LoadType) | ||||||
|             await typeSystem.LoadType(node.DataType); |             await typeSystem.LoadType(node.DataType).ConfigureAwait(false); | ||||||
|         _variableDicts.AddOrUpdate(nodeIdStr, node); |         _variableDicts.AddOrUpdate(nodeIdStr, node); | ||||||
|         return node; |         return node; | ||||||
|     } |     } | ||||||
| @@ -781,7 +786,7 @@ public class OPCUAClient : IDisposable | |||||||
|             if (StatusCode.IsGood(nodes.Item2[i].StatusCode)) |             if (StatusCode.IsGood(nodes.Item2[i].StatusCode)) | ||||||
|             { |             { | ||||||
|                 var node = ((VariableNode)nodes.Item1[i]); |                 var node = ((VariableNode)nodes.Item1[i]); | ||||||
|                 await typeSystem.LoadType(node.DataType); |                 await typeSystem.LoadType(node.DataType).ConfigureAwait(false); | ||||||
|                 _variableDicts.AddOrUpdate(nodeIdStrs[i], node); |                 _variableDicts.AddOrUpdate(nodeIdStrs[i], node); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| #region copyright | #region copyright | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
| @@ -9,7 +8,6 @@ | |||||||
| //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
| //  QQ群:605534569 | //  QQ群:605534569 | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
| using Opc.Ua; | using Opc.Ua; | ||||||
|   | |||||||
| @@ -7,8 +7,8 @@ | |||||||
|  |  | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| 		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | 		<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" Version="1.4.372.76" /> | ||||||
| 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.56" /> | 		<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.76" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -36,11 +36,42 @@ internal partial class SiemensHelper | |||||||
|     //    return OperResult.CreateSuccessResult<byte[]>(numArray); |     //    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 length = 0; | ||||||
|         int itemLen = (sends.Length - 19) / 12; |         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++) |         for (int index = 0; index < itemLen; index++) | ||||||
|         { |         { | ||||||
|             if (sends[22 + (index * 12)] >= (byte)S7WordLength.Word) |             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]; |         byte[] dataArray = new byte[length]; | ||||||
| @@ -105,29 +136,39 @@ internal partial class SiemensHelper | |||||||
|                 } |                 } | ||||||
|                 else |                 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) |         if (content.Length < 22) | ||||||
|         { |         { | ||||||
|             return new OperResult<byte[]>() { Message = "未知错误" }; |             return new() | ||||||
|  |             { | ||||||
|  |                 Message = "长度不足", | ||||||
|  |                 Content2 = FilterResult.Success | ||||||
|  |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         byte err = content[21]; |         byte err = content[21]; | ||||||
|         if (err != byte.MaxValue) |         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 |         else | ||||||
|         { |         { | ||||||
|             return OperResult.CreateSuccessResult(content); |             return OperResult.CreateSuccessResult(content, FilterResult.Success); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -123,34 +123,7 @@ namespace ThingsGateway.Foundation.Adapter.Siemens | |||||||
|         #region 设置 |         #region 设置 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 远程TSAP,需重新连接 |         /// 本地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,需重新连接 |  | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public int LocalTSAP |         public int LocalTSAP | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -35,10 +35,10 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte | |||||||
|     /// <inheritdoc/> |     /// <inheritdoc/> | ||||||
|     protected override FilterResult UnpackResponse(SiemensMessage request, byte[] send, byte[] body, byte[] response) |     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) |         if (response[2] * 256 + response[3] == 7) | ||||||
|         { |         { | ||||||
|             result = new OperResult<byte[]>() { Content = response }; |             result = new() { Content = response, Content2 = FilterResult.Success }; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -56,6 +56,6 @@ public class SiemensS7PLCDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapte | |||||||
|         request.ErrorCode = result.ErrorCode; |         request.ErrorCode = result.ErrorCode; | ||||||
|         request.Message = result.Message; |         request.Message = result.Message; | ||||||
|         request.Content = result.Content; |         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错误; 资源集不存在 | ||||||
| @@ -207,7 +207,7 @@ public interface IReadWrite : IDisposable | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 读写超时时间 |     /// 读写超时时间 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     ushort TimeOut { get; set; } |     int TimeOut { get; set; } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 一个寄存器所占的字节长度 |     /// 一个寄存器所占的字节长度 | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ public abstract class ReadWriteDevicesBase : IReadWrite | |||||||
|  |  | ||||||
|     /// <inheritdoc/> |     /// <inheritdoc/> | ||||||
|     [Description("读写超时时间")] |     [Description("读写超时时间")] | ||||||
|     public ushort TimeOut { get; set; } = 3000; |     public int TimeOut { get; set; } = 3000; | ||||||
|  |  | ||||||
|     /// <inheritdoc/> |     /// <inheritdoc/> | ||||||
|     public bool CascadeDisposal { get; set; } = true; |     public bool CascadeDisposal { get; set; } = true; | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase | |||||||
|     public ReadWriteDevicesSerialSessionBase(SerialSession serialSession) |     public ReadWriteDevicesSerialSessionBase(SerialSession serialSession) | ||||||
|     { |     { | ||||||
|         SerialSession = serialSession; |         SerialSession = serialSession; | ||||||
|         WaitingClientEx = SerialSession.CreateWaitingClient(new() { ThrowBreakException = true }); |         WaitingClientEx = SerialSession.CreateWaitingClient(new() { }); | ||||||
|         SerialSession.Received -= Received; |         SerialSession.Received -= Received; | ||||||
|         SerialSession.Connecting -= Connecting; |         SerialSession.Connecting -= Connecting; | ||||||
|         SerialSession.Connected -= Connected; |         SerialSession.Connected -= Connected; | ||||||
| @@ -96,7 +96,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; |             waitingOptions ??= new WaitingOptions { }; | ||||||
|             ResponsedData result = SerialSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); |             ResponsedData result = SerialSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||||
|             return OperResult.CreateSuccessResult(result.Data); |             return OperResult.CreateSuccessResult(result.Data); | ||||||
|         } |         } | ||||||
| @@ -111,7 +111,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; |             waitingOptions ??= new WaitingOptions { }; | ||||||
|             ResponsedData result = await SerialSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); |             ResponsedData result = await SerialSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||||
|             return OperResult.CreateSuccessResult(result.Data); |             return OperResult.CreateSuccessResult(result.Data); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | |||||||
|     public ReadWriteDevicesTcpClientBase(TcpClient tcpClient) |     public ReadWriteDevicesTcpClientBase(TcpClient tcpClient) | ||||||
|     { |     { | ||||||
|         TcpClient = tcpClient; |         TcpClient = tcpClient; | ||||||
|         WaitingClientEx = TcpClient.CreateWaitingClient(new() { ThrowBreakException = true }); |         WaitingClientEx = TcpClient.CreateWaitingClient(new() { }); | ||||||
|         TcpClient.Connecting -= Connecting; |         TcpClient.Connecting -= Connecting; | ||||||
|         TcpClient.Connected -= Connected; |         TcpClient.Connected -= Connected; | ||||||
|         TcpClient.Disconnecting -= Disconnecting; |         TcpClient.Disconnecting -= Disconnecting; | ||||||
| @@ -86,7 +86,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true, }; |             waitingOptions ??= new WaitingOptions { }; | ||||||
|             ResponsedData result = TcpClient.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); |             ResponsedData result = TcpClient.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||||
|             return OperResult.CreateSuccessResult(result.Data); |             return OperResult.CreateSuccessResult(result.Data); | ||||||
|         } |         } | ||||||
| @@ -101,7 +101,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; |             waitingOptions ??= new WaitingOptions { }; | ||||||
|             ResponsedData result = await TcpClient.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); |             ResponsedData result = await TcpClient.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||||
|             return OperResult.CreateSuccessResult(result.Data); |             return OperResult.CreateSuccessResult(result.Data); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -55,7 +55,8 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase | |||||||
|     /// <inheritdoc/> |     /// <inheritdoc/> | ||||||
|     public override Task ConnectAsync(CancellationToken cancellationToken) |     public override Task ConnectAsync(CancellationToken cancellationToken) | ||||||
|     { |     { | ||||||
|         return Task.Run(() => TcpService.Start()); |         Connect(cancellationToken); | ||||||
|  |         return EasyTask.CompletedTask; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <inheritdoc/> |     /// <inheritdoc/> | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         UdpSession = udpSession; |         UdpSession = udpSession; | ||||||
|         SetDataAdapter(); |         SetDataAdapter(); | ||||||
|         WaitingClientEx = UdpSession.CreateWaitingClient(new() { ThrowBreakException = true }); |         WaitingClientEx = UdpSession.CreateWaitingClient(new() { }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -64,7 +64,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; |             waitingOptions ??= new WaitingOptions { }; | ||||||
|             ResponsedData result = UdpSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); |             ResponsedData result = UdpSession.CreateWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); | ||||||
|             return OperResult.CreateSuccessResult(result.Data); |             return OperResult.CreateSuccessResult(result.Data); | ||||||
|         } |         } | ||||||
| @@ -79,7 +79,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase | |||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             waitingOptions ??= new WaitingOptions { ThrowBreakException = true }; |             waitingOptions ??= new WaitingOptions { }; | ||||||
|             ResponsedData result = await UdpSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); |             ResponsedData result = await UdpSession.CreateWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); | ||||||
|             return OperResult.CreateSuccessResult(result.Data); |             return OperResult.CreateSuccessResult(result.Data); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -51,10 +51,10 @@ public sealed class EasyLock | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 进入锁 |     /// 进入锁 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public void Wait() |     public void Wait(CancellationToken cancellationToken = default) | ||||||
|     { |     { | ||||||
|         Interlocked.Increment(ref lockWaitCount); |         Interlocked.Increment(ref lockWaitCount); | ||||||
|         m_waiterLock.Wait(); |         m_waiterLock.Wait(cancellationToken); | ||||||
|         Interlocked.Decrement(ref lockWaitCount); |         Interlocked.Decrement(ref lockWaitCount); | ||||||
|     } |     } | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -71,10 +71,10 @@ public sealed class EasyLock | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 进入锁 |     /// 进入锁 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public async Task WaitAsync() |     public async Task WaitAsync(CancellationToken cancellationToken = default) | ||||||
|     { |     { | ||||||
|         Interlocked.Increment(ref lockWaitCount); |         Interlocked.Increment(ref lockWaitCount); | ||||||
|         await m_waiterLock.WaitAsync(); |         await m_waiterLock.WaitAsync(cancellationToken); | ||||||
|         Interlocked.Decrement(ref lockWaitCount); |         Interlocked.Decrement(ref lockWaitCount); | ||||||
|     } |     } | ||||||
|     /// <summary> |     /// <summary> | ||||||
|   | |||||||
| @@ -10,6 +10,8 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Foundation.Extension.Generic; | using ThingsGateway.Foundation.Extension.Generic; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Foundation.Core; | namespace ThingsGateway.Foundation.Core; | ||||||
| @@ -19,6 +21,10 @@ namespace ThingsGateway.Foundation.Core; | |||||||
| /// </summary> | /// </summary> | ||||||
| public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDataHandlingAdapter<TRequest> where TRequest : class, IMessage | 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}"/> |     /// <inheritdoc cref="ReadWriteDevicesTcpDataHandleAdapter{TRequest}"/> | ||||||
|     public ReadWriteDevicesTcpDataHandleAdapter() |     public ReadWriteDevicesTcpDataHandleAdapter() | ||||||
|     { |     { | ||||||
| @@ -46,7 +52,7 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | |||||||
|     { |     { | ||||||
|         //获取全部内容 |         //获取全部内容 | ||||||
|         var allBytes = byteBlock.ToArray(0, byteBlock.Len); |         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 |         //缓存/不缓存解析一样,因为游标已经归0 | ||||||
|         { |         { | ||||||
|             request = Request; |             request = Request; | ||||||
| @@ -131,7 +137,7 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 发送方法,会重新建立<see cref="Request"/> |     /// 发送方法,会重新建立<see cref="Request"/> | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     protected void GoSend(byte[] item) |     protected virtual void GoSend(byte[] item) | ||||||
|     { |     { | ||||||
|         byte[] bytes; |         byte[] bytes; | ||||||
|         if (IsSendPackCommand) |         if (IsSendPackCommand) | ||||||
| @@ -141,12 +147,12 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | |||||||
|         Request = GetInstance(); |         Request = GetInstance(); | ||||||
|         Request.SendBytes = bytes; |         Request.SendBytes = bytes; | ||||||
|         GoSend(bytes, 0, bytes.Length); |         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> |     /// <summary> | ||||||
|     /// 发送方法,会重新建立<see cref="Request"/> |     /// 发送方法,会重新建立<see cref="Request"/> | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     protected async Task GoSendAsync(byte[] item) |     protected virtual async Task GoSendAsync(byte[] item) | ||||||
|     { |     { | ||||||
|         byte[] bytes; |         byte[] bytes; | ||||||
|         if (IsSendPackCommand) |         if (IsSendPackCommand) | ||||||
| @@ -156,7 +162,7 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | |||||||
|         Request = GetInstance(); |         Request = GetInstance(); | ||||||
|         Request.SendBytes = bytes; |         Request.SendBytes = bytes; | ||||||
|         await GoSendAsync(bytes, 0, bytes.Length); |         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/> |     /// <inheritdoc/> | ||||||
| @@ -180,6 +186,13 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat | |||||||
|     /// <inheritdoc/> |     /// <inheritdoc/> | ||||||
|     public override string ToString() |     public override string ToString() | ||||||
|     { |     { | ||||||
|         return Owner.ToString(); |         if (Owner is SocketClient client) | ||||||
|  |         { | ||||||
|  |             return client.GetIPPort(); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             return Owner.ToString(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -11,6 +11,7 @@ | |||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
| using System.Net; | using System.Net; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Foundation.Extension.Generic; | using ThingsGateway.Foundation.Extension.Generic; | ||||||
|  |  | ||||||
| @@ -21,6 +22,13 @@ namespace ThingsGateway.Foundation.Core; | |||||||
| /// </summary> | /// </summary> | ||||||
| public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHandlingAdapter where TRequest : class, IMessage | public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHandlingAdapter where TRequest : class, IMessage | ||||||
| { | { | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// 报文输出时采用字符串还是HexString | ||||||
|  |     /// </summary> | ||||||
|  |     public virtual bool IsHexData { get; set; } = true; | ||||||
|  |  | ||||||
|     /// <inheritdoc cref="ReadWriteDevicesUdpDataHandleAdapter{TRequest}"/> |     /// <inheritdoc cref="ReadWriteDevicesUdpDataHandleAdapter{TRequest}"/> | ||||||
|     public ReadWriteDevicesUdpDataHandleAdapter() |     public ReadWriteDevicesUdpDataHandleAdapter() | ||||||
|     { |     { | ||||||
| @@ -68,13 +76,13 @@ public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHa | |||||||
|         Request = GetInstance(); |         Request = GetInstance(); | ||||||
|         Request.SendBytes = bytes; |         Request.SendBytes = bytes; | ||||||
|         GoSend(endPoint, bytes, 0, bytes.Length); |         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/> |     /// <inheritdoc/> | ||||||
|     protected override void PreviewReceived(EndPoint remoteEndPoint, ByteBlock byteBlock) |     protected override void PreviewReceived(EndPoint remoteEndPoint, ByteBlock byteBlock) | ||||||
|     { |     { | ||||||
|         var allBytes = byteBlock.ToArray(0, byteBlock.Len); |         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) |         if (Request?.SendBytes == null) | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -10,6 +10,8 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Foundation.Extension.Generic; | using ThingsGateway.Foundation.Extension.Generic; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Foundation.Core; | namespace ThingsGateway.Foundation.Core; | ||||||
| @@ -17,6 +19,39 @@ namespace ThingsGateway.Foundation.Core; | |||||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||||
| public static class ByteExtensions | 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> |     /// <summary> | ||||||
|     /// 获取byte数据类型的第offset位,是否为True<br /> |     /// 获取byte数据类型的第offset位,是否为True<br /> | ||||||
|     /// </summary> |     /// </summary> | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
|  | using System.Globalization; | ||||||
| using System.Net; | using System.Net; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
| @@ -114,17 +115,47 @@ public static class StringExtensions | |||||||
|         else if (propertyType == typeof(sbyte)) |         else if (propertyType == typeof(sbyte)) | ||||||
|             _value = sbyte.Parse(value); |             _value = sbyte.Parse(value); | ||||||
|         else if (propertyType == typeof(short)) |         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)) |         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)) |         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)) |         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)) |         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)) |         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)) |         else if (propertyType == typeof(float)) | ||||||
|             _value = float.Parse(value); |             _value = float.Parse(value); | ||||||
|         else if (propertyType == typeof(double)) |         else if (propertyType == typeof(double)) | ||||||
| @@ -142,7 +173,6 @@ public static class StringExtensions | |||||||
|         else if (propertyType.IsEnum) |         else if (propertyType.IsEnum) | ||||||
|             _value = Enum.Parse(propertyType, value); |             _value = Enum.Parse(propertyType, value); | ||||||
|         return _value; |         return _value; | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -72,4 +72,28 @@ namespace ThingsGateway.Foundation.Core | |||||||
|             GC.SuppressFinalize(this); |             GC.SuppressFinalize(this); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | #if NET6_0_OR_GREATER | ||||||
|  |     public partial class DisposableObject : IAsyncDisposable | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 异步释放资源。内部已经处理了<see cref="GC.SuppressFinalize(object)"/> | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public async ValueTask DisposeAsync() | ||||||
|  |         { | ||||||
|  |             await DisposeAsyncCore().ConfigureAwait(false); | ||||||
|  |             Dispose(disposing: false); | ||||||
|  |             GC.SuppressFinalize(this); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 异步释放资源。注意:此方法仅在调用<see cref="IAsyncDisposable.DisposeAsync"/>时有效。 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         protected virtual ValueTask DisposeAsyncCore() | ||||||
|  |         { | ||||||
|  |             return ValueTask.CompletedTask; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | #endif | ||||||
| } | } | ||||||
| @@ -0,0 +1,47 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 | ||||||
|  | //  CSDN博客:https://blog.csdn.net/qq_40374647 | ||||||
|  | //  哔哩哔哩视频:https://space.bilibili.com/94253567 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/RRQM_Home | ||||||
|  | //  Github源代码仓库:https://github.com/RRQM | ||||||
|  | //  API首页:http://rrqm_home.gitee.io/touchsocket/ | ||||||
|  | //  交流QQ群:234762506 | ||||||
|  | //  感谢您的下载和使用 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// ConfigEventArgs | ||||||
|  |     /// </summary> | ||||||
|  |     public class ConfigEventArgs : PluginEventArgs | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// ConfigEventArgs | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="config"></param> | ||||||
|  |         public ConfigEventArgs(TouchSocketConfig config) | ||||||
|  |         { | ||||||
|  |             this.Config = config; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 具体配置 | ||||||
|  |         /// </summary> | ||||||
|  |         public TouchSocketConfig Config { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| #region copyright | #region copyright | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
| @@ -10,24 +10,17 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| #endregion | #endregion | ||||||
| 
 | 
 | ||||||
| namespace ThingsGateway.Foundation.Serial; | namespace ThingsGateway.Foundation.Core | ||||||
| 
 |  | ||||||
| /// <summary> |  | ||||||
| /// 通讯基类 |  | ||||||
| /// </summary> |  | ||||||
| public abstract class BaseSerial : DependencyObject, ISerial |  | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 同步根。 |     /// 具有配置设置的对象 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     protected readonly object SyncRoot = new object(); |     public abstract class ConfigObject : DependencyObject, IConfigObject | ||||||
|  |     { | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public abstract TouchSocketConfig Config { get; } | ||||||
| 
 | 
 | ||||||
|     /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|     public abstract int SendBufferSize { get; } |         public ILog Logger { get; set; } | ||||||
| 
 |     } | ||||||
|     /// <inheritdoc/> |  | ||||||
|     public abstract int ReceiveBufferSize { get; } |  | ||||||
| 
 |  | ||||||
|     /// <inheritdoc/> |  | ||||||
|     public ILog Logger { get; set; } |  | ||||||
| } | } | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 具有配置的对象接口 | ||||||
|  |     /// </summary> | ||||||
|  |     public interface IConfigObject : IDependencyObject, ILoggerObject | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置项 | ||||||
|  |         /// </summary> | ||||||
|  |         TouchSocketConfig Config { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 | ||||||
|  | //  CSDN博客:https://blog.csdn.net/qq_40374647 | ||||||
|  | //  哔哩哔哩视频:https://space.bilibili.com/94253567 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/RRQM_Home | ||||||
|  | //  Github源代码仓库:https://github.com/RRQM | ||||||
|  | //  API首页:http://rrqm_home.gitee.io/touchsocket/ | ||||||
|  | //  交流QQ群:234762506 | ||||||
|  | //  感谢您的下载和使用 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 当配置Config完成时触发。 | ||||||
|  |     /// </summary> | ||||||
|  |     public interface ILoadedConfigPlugin<in TSender> : IPlugin where TSender : IConfigObject | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 当完成配置载入时 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="sender"></param> | ||||||
|  |         /// <param name="e"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         Task OnLoadedConfig(TSender sender, ConfigEventArgs e); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// 当配置Config完成时触发。 | ||||||
|  |     /// </summary> | ||||||
|  |     public interface ILoadedConfigPlugin : ILoadedConfigPlugin<IConfigObject> | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,34 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 当正在配置Config时触发。 | ||||||
|  |     /// </summary> | ||||||
|  |     public interface ILoadingConfigPlugin<in TSender> : IPlugin where TSender : IConfigObject | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 当载入配置时 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="sender"></param> | ||||||
|  |         /// <param name="e"></param> | ||||||
|  |         Task OnLoadingConfig(TSender sender, ConfigEventArgs e); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// ILoadingConfigPlugin | ||||||
|  |     /// </summary> | ||||||
|  |     public interface ILoadingConfigPlugin : ILoadingConfigPlugin<IConfigObject> | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 具有设置配置的对象接口 | ||||||
|  |     /// </summary> | ||||||
|  |     public interface ISetupConfigObject : IConfigObject, IPluginObject | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 配置设置项 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="config"></param> | ||||||
|  |         /// <exception cref="Exception"></exception> | ||||||
|  |         void Setup(TouchSocketConfig config); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,102 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 具有设置配置的对象 | ||||||
|  |     /// </summary> | ||||||
|  |     public abstract class SetupConfigObject : ConfigObject, ISetupConfigObject | ||||||
|  |     { | ||||||
|  |         private TouchSocketConfig m_config; | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public override TouchSocketConfig Config => this.m_config; | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public IContainer Container { get; private set; } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public IPluginsManager PluginsManager { get; private set; } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public void Setup(TouchSocketConfig config) | ||||||
|  |         { | ||||||
|  |             if (config == null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(config)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             this.ThrowIfDisposed(); | ||||||
|  |  | ||||||
|  |             this.BuildConfig(config); | ||||||
|  |  | ||||||
|  |             this.PluginsManager?.Raise(nameof(ILoadingConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config)); | ||||||
|  |             this.LoadConfig(this.Config); | ||||||
|  |             this.PluginsManager?.Raise(nameof(ILoadedConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 加载配置 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="config"></param> | ||||||
|  |         protected virtual void LoadConfig(TouchSocketConfig config) | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void BuildConfig(TouchSocketConfig config) | ||||||
|  |         { | ||||||
|  |             this.m_config = config; | ||||||
|  |  | ||||||
|  |             if (!config.TryGetValue(TouchSocketCoreConfigExtension.ContainerProperty, out var container)) | ||||||
|  |             { | ||||||
|  |                 container = new Container(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (!container.IsRegistered(typeof(ILog))) | ||||||
|  |             { | ||||||
|  |                 container.RegisterSingleton<ILog, LoggerGroup>(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (!(config.GetValue(TouchSocketCoreConfigExtension.PluginsManagerProperty) is IPluginsManager pluginsManager)) | ||||||
|  |             { | ||||||
|  |                 pluginsManager = new PluginsManager(container); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (container.IsRegistered(typeof(IPluginsManager))) | ||||||
|  |             { | ||||||
|  |                 pluginsManager = container.Resolve<IPluginsManager>(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 container.RegisterSingleton<IPluginsManager>(pluginsManager); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (config.GetValue(TouchSocketCoreConfigExtension.ConfigureContainerProperty) is Action<IContainer> actionContainer) | ||||||
|  |             { | ||||||
|  |                 actionContainer.Invoke(container); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (config.GetValue(TouchSocketCoreConfigExtension.ConfigurePluginsProperty) is Action<IPluginsManager> actionPluginsManager) | ||||||
|  |             { | ||||||
|  |                 pluginsManager.Enable = true; | ||||||
|  |                 actionPluginsManager.Invoke(pluginsManager); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             this.Logger ??= container.Resolve<ILog>(); | ||||||
|  |  | ||||||
|  |             this.Container = container; | ||||||
|  |             this.PluginsManager = pluginsManager; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -28,8 +28,22 @@ namespace ThingsGateway.Foundation.Core | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 配置文件基类 |     /// 配置文件基类 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class TouchSocketConfig : DependencyObject |     public class TouchSocketConfig : DependencyObject, ICloneable | ||||||
|     { |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 克隆配置依赖项,并返回一个新的克隆对象。 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public TouchSocketConfig Clone() | ||||||
|  |         { | ||||||
|  |             var config = new TouchSocketConfig(); | ||||||
|  |             this.CloneTo(config, true); | ||||||
|  |             return config; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         object ICloneable.Clone() | ||||||
|  |         { | ||||||
|  |             return this.Clone(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -28,17 +28,17 @@ namespace ThingsGateway.Foundation.Core | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 单线程流式适配器配置 |     /// 单线程流式适配器配置 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class SingleStreamAdapterOption |     public class AdapterOption | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 适配器数据包缓存启用。默认为缺省(null),如果有正常值会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> |         /// 适配器数据包缓存启用。默认为缺省(null),如果有正常值会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public bool? CacheTimeoutEnable { get; set; } = true; |         public bool? CacheTimeoutEnable { get; set; } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 适配器数据包缓存时长。默认为缺省(null)。当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> |         /// 适配器数据包缓存时长。默认为缺省(null)。当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public int? CacheTimeout { get; set; } |         public TimeSpan? CacheTimeout { get; set; } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 适配器数据包最大值。默认缺省(null),当该值有效时会在设置适配器时,直接作用于<see cref="DataHandlingAdapter.MaxPackageSize"/> |         /// 适配器数据包最大值。默认缺省(null),当该值有效时会在设置适配器时,直接作用于<see cref="DataHandlingAdapter.MaxPackageSize"/> | ||||||
| @@ -103,12 +103,12 @@ namespace ThingsGateway.Foundation.Core | |||||||
|                 { |                 { | ||||||
|                     return FilterResult.Cache; |                     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; |                     return FilterResult.GoOn; | ||||||
|                 } |                 } | ||||||
|                 byteBlock.Pos += this.StartCode.Length; |                 byteBlock.Pos += indexStart + 1; | ||||||
|                 request = requestInfo; |                 request = requestInfo; | ||||||
|  |  | ||||||
|                 int len; |                 int len; | ||||||
|   | |||||||
| @@ -26,92 +26,62 @@ namespace ThingsGateway.Foundation.Core | |||||||
|         /// <param name="config"></param> |         /// <param name="config"></param> | ||||||
|         public static void Config(this SingleStreamDataHandlingAdapter adapter, TouchSocketConfig config) |         public static void Config(this SingleStreamDataHandlingAdapter adapter, TouchSocketConfig config) | ||||||
|         { |         { | ||||||
|             if (config.GetValue(DataHandlingAdapterExtension.MaxPackageSizeProperty) is int v1) |             var option = config.GetValue(AdapterOptionProperty) ?? throw new ArgumentNullException(nameof(AdapterOptionProperty)); | ||||||
|  |  | ||||||
|  |             if (option.MaxPackageSize.HasValue) | ||||||
|             { |             { | ||||||
|                 adapter.MaxPackageSize = v1; |                 adapter.MaxPackageSize = option.MaxPackageSize.Value; | ||||||
|             } |             } | ||||||
|             if (config.GetValue(DataHandlingAdapterExtension.CacheTimeoutProperty) != TimeSpan.Zero) |  | ||||||
|  |             if (option.CacheTimeout.HasValue) | ||||||
|             { |             { | ||||||
|                 adapter.CacheTimeout = config.GetValue(DataHandlingAdapterExtension.CacheTimeoutProperty); |                 adapter.CacheTimeout = option.CacheTimeout.Value; | ||||||
|             } |             } | ||||||
|             if (config.GetValue(DataHandlingAdapterExtension.CacheTimeoutEnableProperty) is bool v2) |  | ||||||
|  |             if (option.CacheTimeoutEnable.HasValue) | ||||||
|             { |             { | ||||||
|                 adapter.CacheTimeoutEnable = v2; |                 adapter.CacheTimeoutEnable = option.CacheTimeoutEnable.Value; | ||||||
|             } |             } | ||||||
|             if (config.GetValue(DataHandlingAdapterExtension.UpdateCacheTimeWhenRevProperty) is bool v3) |  | ||||||
|  |             if (option.UpdateCacheTimeWhenRev.HasValue) | ||||||
|             { |             { | ||||||
|                 adapter.UpdateCacheTimeWhenRev = v3; |                 adapter.UpdateCacheTimeWhenRev = option.UpdateCacheTimeWhenRev.Value; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 将<see cref="TouchSocketConfig"/>中的配置,装载在<see cref="SingleStreamDataHandlingAdapter"/>上。 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="adapter"></param> | ||||||
|  |         /// <param name="config"></param> | ||||||
|  |         public static void Config(this DataHandlingAdapter adapter, TouchSocketConfig config) | ||||||
|  |         { | ||||||
|  |             var option = config.GetValue(AdapterOptionProperty) ?? throw new ArgumentNullException(nameof(AdapterOptionProperty)); | ||||||
|  |  | ||||||
|  |             if (option.MaxPackageSize.HasValue) | ||||||
|  |             { | ||||||
|  |                 adapter.MaxPackageSize = option.MaxPackageSize.Value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         #endregion |         #endregion | ||||||
|  |  | ||||||
|         #region 适配器配置 |         #region 适配器配置 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 适配器数据包缓存启用。默认为缺省(null),如果有正常值会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> |         /// 设置适配器相关的配置 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static readonly DependencyProperty<bool?> CacheTimeoutEnableProperty = DependencyProperty<bool?>.Register("CacheTimeoutEnable", null); |         public static readonly DependencyProperty<AdapterOption> AdapterOptionProperty = DependencyProperty<AdapterOption>.Register("AdapterOption", new AdapterOption()); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 适配器数据包缓存时长。默认为缺省(<see cref="TimeSpan.Zero"/>)。当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> |         /// 设置适配器相关的配置 | ||||||
|         /// </summary> |  | ||||||
|         public static readonly DependencyProperty<TimeSpan> CacheTimeoutProperty = DependencyProperty<TimeSpan>.Register("CacheTimeout", TimeSpan.Zero); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 适配器数据包最大值。默认缺省(null),当该值有效时会在设置适配器时,直接作用于<see cref="DataHandlingAdapter.MaxPackageSize"/> |  | ||||||
|         /// </summary> |  | ||||||
|         public static readonly DependencyProperty<int?> MaxPackageSizeProperty = DependencyProperty<int?>.Register("MaxPackageSize", null); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 适配器数据包缓存策略。默认缺省(null),当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.UpdateCacheTimeWhenRev"/> |  | ||||||
|         /// </summary> |  | ||||||
|         public static readonly DependencyProperty<bool?> UpdateCacheTimeWhenRevProperty = DependencyProperty<bool?>.Register("UpdateCacheTimeWhenRev", null); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 适配器数据包缓存时长。默认为缺省(<see cref="TimeSpan.Zero"/>)。当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeout"/> |  | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="config"></param> |         /// <param name="config"></param> | ||||||
|         /// <param name="value"></param> |         /// <param name="value"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static TouchSocketConfig SetCacheTimeout(this TouchSocketConfig config, TimeSpan value) |         public static TouchSocketConfig SetAdapterOption(this TouchSocketConfig config, AdapterOption value) | ||||||
|         { |         { | ||||||
|             config.SetValue(CacheTimeoutProperty, value); |             config.SetValue(AdapterOptionProperty, value); | ||||||
|             return config; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 适配器数据包缓存启用。默认为缺省(null),如果有正常值会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.CacheTimeoutEnable"/> |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <param name="value"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public static TouchSocketConfig SetCacheTimeoutEnable(this TouchSocketConfig config, bool value) |  | ||||||
|         { |  | ||||||
|             config.SetValue(CacheTimeoutEnableProperty, value); |  | ||||||
|             return config; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 适配器数据包最大值。默认缺省(null),当该值有效时会在设置适配器时,直接作用于<see cref="DataHandlingAdapter.MaxPackageSize"/> |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <param name="value"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public static TouchSocketConfig SetMaxPackageSize(this TouchSocketConfig config, int value) |  | ||||||
|         { |  | ||||||
|             config.SetValue(MaxPackageSizeProperty, value); |  | ||||||
|             return config; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 适配器数据包缓存策略。默认缺省(null),当该值有效时会在设置适配器时,直接作用于<see cref="SingleStreamDataHandlingAdapter.UpdateCacheTimeWhenRev"/> |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <param name="value"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public static TouchSocketConfig SetUpdateCacheTimeWhenRev(this TouchSocketConfig config, bool value) |  | ||||||
|         { |  | ||||||
|             config.SetValue(UpdateCacheTimeWhenRevProperty, value); |  | ||||||
|             return config; |             return config; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -96,5 +96,45 @@ namespace ThingsGateway.Foundation.Core | |||||||
|             this.m_dp.Clear(); |             this.m_dp.Clear(); | ||||||
|             base.Dispose(disposing); |             base.Dispose(disposing); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 将当前对象的依赖项克隆到目标对象中 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="dependencyObject">目标对象</param> | ||||||
|  |         /// <param name="overwrite">当目标对象中存在相同依赖项时,是或否覆盖</param> | ||||||
|  |         /// <exception cref="ArgumentNullException"></exception> | ||||||
|  |         /// <exception cref="ObjectDisposedException"></exception> | ||||||
|  |         protected void CloneTo(DependencyObject dependencyObject, bool overwrite) | ||||||
|  |         { | ||||||
|  |             if (dependencyObject is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(dependencyObject)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (dependencyObject.DisposedValue) | ||||||
|  |             { | ||||||
|  |                 throw new ObjectDisposedException(nameof(dependencyObject)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             this.ThrowIfDisposed(); | ||||||
|  |  | ||||||
|  |             foreach (var item in this.m_dp) | ||||||
|  |             { | ||||||
|  |                 if (dependencyObject.m_dp.ContainsKey(item.Key)) | ||||||
|  |                 { | ||||||
|  |                     if (overwrite) | ||||||
|  |                     { | ||||||
|  |                         dependencyObject.m_dp.Remove(item.Key); | ||||||
|  |                         dependencyObject.m_dp.Add(item.Key, item.Value); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     dependencyObject.m_dp.Add(item.Key, item.Value); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -189,7 +189,7 @@ namespace ThingsGateway.Foundation.Core | |||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static IEnumerable<string> GetTupleElementNames(this ParameterInfo parameter) |         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> |         /// <summary> | ||||||
| @@ -199,7 +199,7 @@ namespace ThingsGateway.Foundation.Core | |||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static IEnumerable<string> GetTupleElementNames(this MemberInfo memberInfo) |         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 |         #endregion | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,6 +23,8 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Foundation.Core | namespace ThingsGateway.Foundation.Core | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -49,5 +51,69 @@ namespace ThingsGateway.Foundation.Core | |||||||
|         { |         { | ||||||
|             task.ConfigureAwait(false).GetAwaiter().GetResult(); |             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); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 异步等待指定最大时间 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="TResult"></typeparam> | ||||||
|  |         /// <param name="task"></param> | ||||||
|  |         /// <param name="timeout"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         /// <exception cref="TimeoutException"></exception> | ||||||
|  |         public static async Task<TResult> WaitAsync<TResult>(this Task<TResult> task, TimeSpan timeout) | ||||||
|  |         { | ||||||
|  |             using (var timeoutCancellationTokenSource = new CancellationTokenSource()) | ||||||
|  |             { | ||||||
|  |                 var delayTask = Task.Delay(timeout, timeoutCancellationTokenSource.Token); | ||||||
|  |                 if (await Task.WhenAny(task, delayTask) == task) | ||||||
|  |                 { | ||||||
|  |                     timeoutCancellationTokenSource.Cancel(); | ||||||
|  |                     return await task; | ||||||
|  |                 } | ||||||
|  |                 throw new TimeoutException(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 异步等待指定最大时间 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="task"></param> | ||||||
|  |         /// <param name="timeout"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         /// <exception cref="TimeoutException"></exception> | ||||||
|  |         public static async Task WaitAsync(this Task task, TimeSpan timeout) | ||||||
|  |         { | ||||||
|  |             using (var timeoutCancellationTokenSource = new CancellationTokenSource()) | ||||||
|  |             { | ||||||
|  |                 var delayTask = Task.Delay(timeout, timeoutCancellationTokenSource.Token); | ||||||
|  |                 if (await Task.WhenAny(task, delayTask) == task) | ||||||
|  |                 { | ||||||
|  |                     timeoutCancellationTokenSource.Cancel(); | ||||||
|  |                     await task; | ||||||
|  |                 } | ||||||
|  |                 throw new TimeoutException(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -23,22 +23,16 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| 
 | 
 | ||||||
| namespace ThingsGateway.Foundation.Rpc | namespace ThingsGateway.Foundation.Core | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 函数标识 |     /// 具有日志记录器的对象接口 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     [Flags] |     public interface ILoggerObject | ||||||
|     public enum MethodFlags |  | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 空 |         /// 日志记录器 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         None = 1, |         ILog Logger { get; set; } | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// 包含调用上下文 |  | ||||||
|         /// </summary> |  | ||||||
|         IncludeCallContext = 2 |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -11,6 +11,7 @@ | |||||||
| #endregion | #endregion | ||||||
|  |  | ||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  |  | ||||||
| #if NET6_0_OR_GREATER | #if NET6_0_OR_GREATER | ||||||
| using System.Numerics; | using System.Numerics; | ||||||
| @@ -55,12 +56,11 @@ namespace ThingsGateway.Foundation.Core | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             var capacity = 0L; |             var capacity = 0L; | ||||||
|             var poolId = this.Id; |  | ||||||
|             var maxBuckets = SelectBucketIndex(maxArrayLength); |             var maxBuckets = SelectBucketIndex(maxArrayLength); | ||||||
|             var buckets = new Bucket[maxBuckets + 1]; |             var buckets = new Bucket[maxBuckets + 1]; | ||||||
|             for (var i = 0; i < buckets.Length; i++) |             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; |                 long num = GetMaxSizeForBucket(i) * maxArraysPerBucket; | ||||||
|                 capacity += num; |                 capacity += num; | ||||||
|             } |             } | ||||||
| @@ -183,16 +183,19 @@ namespace ThingsGateway.Foundation.Core | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="size"></param> |         /// <param name="size"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|  |         [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||||
|         public static int HitSize(int size) |         public static int HitSize(int size) | ||||||
|         { |         { | ||||||
|             return GetMaxSizeForBucket(SelectBucketIndex(size)); |             return GetMaxSizeForBucket(SelectBucketIndex(size)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||||
|         internal static int GetMaxSizeForBucket(int binIndex) |         internal static int GetMaxSizeForBucket(int binIndex) | ||||||
|         { |         { | ||||||
|             return 16 << binIndex; |             return 16 << binIndex; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||||
|         internal static int SelectBucketIndex(int bufferSize) |         internal static int SelectBucketIndex(int bufferSize) | ||||||
|         { |         { | ||||||
| #if NET6_0_OR_GREATER | #if NET6_0_OR_GREATER | ||||||
| @@ -208,18 +211,16 @@ namespace ThingsGateway.Foundation.Core | |||||||
|             internal readonly int m_bufferLength; |             internal readonly int m_bufferLength; | ||||||
|             private readonly int m_numberOfBuffers; |             private readonly int m_numberOfBuffers; | ||||||
|             private T[][] m_buffers; |             private T[][] m_buffers; | ||||||
|             private readonly int m_poolId; |  | ||||||
|  |  | ||||||
|             private int m_index; |             private int m_index; | ||||||
|             private SpinLock m_lock; |             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_lock = new SpinLock(Debugger.IsAttached); | ||||||
|                 this.m_buffers = new T[numberOfBuffers][]; |                 this.m_buffers = new T[numberOfBuffers][]; | ||||||
|                 this.m_bufferLength = bufferLength; |                 this.m_bufferLength = bufferLength; | ||||||
|                 this.m_numberOfBuffers = numberOfBuffers; |                 this.m_numberOfBuffers = numberOfBuffers; | ||||||
|                 this.m_poolId = poolId; |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             public void Clear() |             public void Clear() | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Core | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 内存池 |     /// 内存池 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class BytePool : ArrayPool<byte> |     public sealed class BytePool : ArrayPool<byte> | ||||||
|     { |     { | ||||||
|         private readonly Timer m_timer; |         private readonly Timer m_timer; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -0,0 +1,49 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 | ||||||
|  | //  CSDN博客:https://blog.csdn.net/qq_40374647 | ||||||
|  | //  哔哩哔哩视频:https://space.bilibili.com/94253567 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/RRQM_Home | ||||||
|  | //  Github源代码仓库:https://github.com/RRQM | ||||||
|  | //  API首页:http://rrqm_home.gitee.io/touchsocket/ | ||||||
|  | //  交流QQ群:234762506 | ||||||
|  | //  感谢您的下载和使用 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Core | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 序列化器 | ||||||
|  |     /// </summary> | ||||||
|  |     /// <typeparam name="TSource"></typeparam> | ||||||
|  |     public interface ISerializer<TSource> | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 序列化 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="target"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         TSource Serialize(object target); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 反序列化 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="source"></param> | ||||||
|  |         /// <param name="targetType"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         object Deserialize(TSource source, Type targetType); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -27,43 +27,48 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 请求关闭 |         /// 请求关闭 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, string> OnClose { get; set; } |         public Func<DmtpActor, string, Task> Closed { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 当创建通道时 |         /// 当创建通道时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, CreateChannelEventArgs> OnCreateChannel { get; set; } |         public Func<DmtpActor, CreateChannelEventArgs, Task> CreatedChannel { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 查找其他IDmtpActor |         /// 查找其他IDmtpActor | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Func<string, IDmtpActor> OnFindDmtpActor { get; set; } |         public Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 在完成握手连接时 |         /// 在完成握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, DmtpVerifyEventArgs> OnHandshaked { get; set; } |         public Func<DmtpActor, DmtpVerifyEventArgs, Task> Handshaked { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 握手 |         /// 握手 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, DmtpVerifyEventArgs> OnHandshaking { get; set; } |         public Func<DmtpActor, DmtpVerifyEventArgs, Task> Handshaking { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 重设Id |         /// 重设Id | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, WaitSetId> OnResetId { get; set; } |         public Func<DmtpActor, IdChangedEventArgs, Task> IdChanged { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 当需要路由的时候 |         /// 当需要路由的时候 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, PackageRouterEventArgs> OnRouting { get; set; } |         public Func<DmtpActor, PackageRouterEventArgs, Task> Routing { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 发送数据接口 |         /// 发送数据接口 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Action<DmtpActor, ArraySegment<byte>[]> OutputSend { get; set; } |         public Action<DmtpActor, ArraySegment<byte>[]> OutputSend { get; set; } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 异步发送数据接口 | ||||||
|  |         /// </summary> | ||||||
|  |         public Func<DmtpActor, ArraySegment<byte>[], Task> OutputSendAsync { get; set; } | ||||||
|  |  | ||||||
|         #endregion 委托 |         #endregion 委托 | ||||||
|  |  | ||||||
|         #region 属性 |         #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> |         /// <summary> | ||||||
|         /// 建立对点 |         /// 建立对点 | ||||||
| @@ -165,7 +144,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 Metadata = metadata |                 Metadata = metadata | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             this.OnHandshaking?.Invoke(this, args); |             this.OnHandshaking(args).GetFalseAwaitResult(); | ||||||
|  |  | ||||||
|             var waitVerify = new WaitVerify() |             var waitVerify = new WaitVerify() | ||||||
|             { |             { | ||||||
| @@ -189,7 +168,8 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             { |                             { | ||||||
|                                 this.Id = verifyResult.Id; |                                 this.Id = verifyResult.Id; | ||||||
|                                 this.IsHandshaked = true; |                                 this.IsHandshaked = true; | ||||||
|                                 this.PrivateHandshaked(new DmtpVerifyEventArgs() |  | ||||||
|  |                                 Task.Factory.StartNew(this.PrivateOnHandshaked, new DmtpVerifyEventArgs() | ||||||
|                                 { |                                 { | ||||||
|                                     Id = verifyResult.Id, |                                     Id = verifyResult.Id, | ||||||
|                                     Metadata = verifyResult.Metadata, |                                     Metadata = verifyResult.Metadata, | ||||||
| @@ -201,18 +181,15 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             else |                             else | ||||||
|                             { |                             { | ||||||
|                                 verifyResult.Handle = true; |                                 verifyResult.Handle = true; | ||||||
|                                 this.Close(false, verifyResult.Message); |  | ||||||
|                                 throw new TokenVerifyException(verifyResult.Message); |                                 throw new TokenVerifyException(verifyResult.Message); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     case WaitDataStatus.Overtime: |                     case WaitDataStatus.Overtime: | ||||||
|                         this.Close(false, TouchSocketDmtpStatus.Overtime.GetDescription()); |  | ||||||
|                         throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription()); |                         throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription()); | ||||||
|                     case WaitDataStatus.Canceled: |                     case WaitDataStatus.Canceled: | ||||||
|                     case WaitDataStatus.Disposed: |                     case WaitDataStatus.Disposed: | ||||||
|                     default: |                     default: | ||||||
|                         this.Close(false, null); |                         throw new OperationCanceledException(); | ||||||
|                         return; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
| @@ -240,7 +217,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 Metadata = metadata |                 Metadata = metadata | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             this.OnHandshaking?.Invoke(this, args); |             await this.OnHandshaking(args).ConfigureFalseAwait(); | ||||||
|  |  | ||||||
|             var waitVerify = new WaitVerify() |             var waitVerify = new WaitVerify() | ||||||
|             { |             { | ||||||
| @@ -253,8 +230,8 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 this.SendJsonObject(P1_Handshake_Request, waitVerify); |                 await this.SendJsonObjectAsync(P1_Handshake_Request, waitVerify).ConfigureFalseAwait(); | ||||||
|                 switch (await waitData.WaitAsync(timeout)) |                 switch (await waitData.WaitAsync(timeout).ConfigureFalseAwait()) | ||||||
|                 { |                 { | ||||||
|                     case WaitDataStatus.SetRunning: |                     case WaitDataStatus.SetRunning: | ||||||
|                         { |                         { | ||||||
| @@ -263,7 +240,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             { |                             { | ||||||
|                                 this.Id = verifyResult.Id; |                                 this.Id = verifyResult.Id; | ||||||
|                                 this.IsHandshaked = true; |                                 this.IsHandshaked = true; | ||||||
|                                 this.PrivateHandshaked(new DmtpVerifyEventArgs() |                                 _ = Task.Factory.StartNew(this.PrivateOnHandshaked, new DmtpVerifyEventArgs() | ||||||
|                                 { |                                 { | ||||||
|                                     Id = verifyResult.Id, |                                     Id = verifyResult.Id, | ||||||
|                                     Metadata = verifyResult.Metadata, |                                     Metadata = verifyResult.Metadata, | ||||||
| @@ -275,18 +252,15 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             else |                             else | ||||||
|                             { |                             { | ||||||
|                                 verifyResult.Handle = true; |                                 verifyResult.Handle = true; | ||||||
|                                 this.Close(false, verifyResult.Message); |  | ||||||
|                                 throw new TokenVerifyException(verifyResult.Message); |                                 throw new TokenVerifyException(verifyResult.Message); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     case WaitDataStatus.Overtime: |                     case WaitDataStatus.Overtime: | ||||||
|                         this.Close(false, TouchSocketDmtpStatus.Overtime.GetDescription()); |  | ||||||
|                         throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription()); |                         throw new TimeoutException(TouchSocketDmtpStatus.Overtime.GetDescription()); | ||||||
|                     case WaitDataStatus.Canceled: |                     case WaitDataStatus.Canceled: | ||||||
|                     case WaitDataStatus.Disposed: |                     case WaitDataStatus.Disposed: | ||||||
|                     default: |                     default: | ||||||
|                         this.Close(false, null); |                         throw new OperationCanceledException(); | ||||||
|                         return; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             finally |             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 |         #region const | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -368,7 +436,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="message"></param> |         /// <param name="message"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public virtual bool InputReceivedData(DmtpMessage message) |         public virtual async Task<bool> InputReceivedData(DmtpMessage message) | ||||||
|         { |         { | ||||||
|             this.LastActiveTime = DateTime.Now; |             this.LastActiveTime = DateTime.Now; | ||||||
|             var byteBlock = message.BodyByteBlock; |             var byteBlock = message.BodyByteBlock; | ||||||
| @@ -376,7 +444,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             { |             { | ||||||
|                 case P0_Close: |                 case P0_Close: | ||||||
|                     { |                     { | ||||||
|                         this.Close(false, message.GetBodyString()); |                         _ = this.OnClosed(false, message.GetBodyString()); | ||||||
|                         return true; |                         return true; | ||||||
|                     } |                     } | ||||||
|                 case P1_Handshake_Request: |                 case P1_Handshake_Request: | ||||||
| @@ -391,11 +459,11 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                                 Metadata = waitVerify.Metadata, |                                 Metadata = waitVerify.Metadata, | ||||||
|                                 Id = waitVerify.Id, |                                 Id = waitVerify.Id, | ||||||
|                             }; |                             }; | ||||||
|                             this.OnHandshaking?.Invoke(this, args); |                             await this.OnHandshaking(args).ConfigureFalseAwait(); | ||||||
|  |  | ||||||
|                             if (args.Id.HasValue()) |                             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; |                                 this.Id = args.Id; | ||||||
|                             } |                             } | ||||||
|  |  | ||||||
| @@ -403,24 +471,23 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             { |                             { | ||||||
|                                 waitVerify.Id = this.Id; |                                 waitVerify.Id = this.Id; | ||||||
|                                 waitVerify.Status = 1; |                                 waitVerify.Status = 1; | ||||||
|                                 this.SendJsonObject(P2_Handshake_Response, waitVerify); |                                 await this.SendJsonObjectAsync(P2_Handshake_Response, waitVerify).ConfigureFalseAwait(); | ||||||
|                                 this.IsHandshaked = true; |                                 this.IsHandshaked = true; | ||||||
|                                 args.Message = "Success"; |                                 args.Message = "Success"; | ||||||
|  |                                 _ = Task.Factory.StartNew(this.PrivateOnHandshaked, args); | ||||||
|                                 Task.Factory.StartNew(this.PrivateHandshaked, args); |  | ||||||
|                             } |                             } | ||||||
|                             else//不允许连接 |                             else//不允许连接 | ||||||
|                             { |                             { | ||||||
|                                 waitVerify.Status = 2; |                                 waitVerify.Status = 2; | ||||||
|                                 waitVerify.Message = args.Message; |                                 waitVerify.Message = args.Message; | ||||||
|                                 this.SendJsonObject(P2_Handshake_Response, waitVerify); |                                 await this.SendJsonObjectAsync(P2_Handshake_Response, waitVerify).ConfigureFalseAwait(); | ||||||
|                                 this.Close(false, args.Message); |                                 _ = this.OnClosed(false, args.Message); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         catch (Exception ex) |                         catch (Exception ex) | ||||||
|                         { |                         { | ||||||
|                             this.Logger.Error(this, $"在protocol={message.ProtocolFlags}中发生错误。信息:{ex.Message}"); |                             this.Logger.Error(this, $"在protocol={message.ProtocolFlags}中发生错误。信息:{ex.Message}"); | ||||||
|                             this.Close(false, ex.Message); |                             _ = this.OnClosed(false, ex.Message); | ||||||
|                         } |                         } | ||||||
|                         return true; |                         return true; | ||||||
|                     } |                     } | ||||||
| @@ -449,7 +516,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             var waitSetId = this.ResolveJsonObject<WaitSetId>(message.GetBodyString()); |                             var waitSetId = this.ResolveJsonObject<WaitSetId>(message.GetBodyString()); | ||||||
|                             try |                             try | ||||||
|                             { |                             { | ||||||
|                                 this.OnResetId?.Invoke(this, waitSetId); |                                 await this.OnIdChanged(new IdChangedEventArgs(waitSetId.OldId, waitSetId.NewId)).ConfigureFalseAwait(); | ||||||
|                                 this.Id = waitSetId.NewId; |                                 this.Id = waitSetId.NewId; | ||||||
|                                 waitSetId.Status = 1; |                                 waitSetId.Status = 1; | ||||||
|                             } |                             } | ||||||
| @@ -458,7 +525,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                                 waitSetId.Status = 2; |                                 waitSetId.Status = 2; | ||||||
|                                 waitSetId.Message = ex.Message; |                                 waitSetId.Message = ex.Message; | ||||||
|                             } |                             } | ||||||
|                             this.SendJsonObject(P4_ResetId_Response, waitSetId); |                             await this.SendJsonObjectAsync(P4_ResetId_Response, waitSetId).ConfigureFalseAwait(); | ||||||
|                         } |                         } | ||||||
|                         catch (Exception ex) |                         catch (Exception ex) | ||||||
|                         { |                         { | ||||||
| @@ -486,11 +553,12 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|                             if (this.AllowRoute && waitPing.Route) |                             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; |                                         return true; | ||||||
|                                     } |                                     } | ||||||
|                                     else |                                     else | ||||||
| @@ -508,7 +576,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                                 waitPing.Status = TouchSocketDmtpStatus.Success.ToValue(); |                                 waitPing.Status = TouchSocketDmtpStatus.Success.ToValue(); | ||||||
|                             } |                             } | ||||||
|                             waitPing.SwitchId(); |                             waitPing.SwitchId(); | ||||||
|                             this.SendJsonObject(P6_Ping_Response, waitPing); |                             await this.SendJsonObjectAsync(P6_Ping_Response, waitPing).ConfigureFalseAwait(); | ||||||
|                         } |                         } | ||||||
|                         catch (Exception ex) |                         catch (Exception ex) | ||||||
|                         { |                         { | ||||||
| @@ -524,9 +592,9 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|                             if (this.AllowRoute && waitPing.Route) |                             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 |                             else | ||||||
| @@ -548,11 +616,11 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             waitCreateChannel.UnpackageRouter(byteBlock); |                             waitCreateChannel.UnpackageRouter(byteBlock); | ||||||
|                             if (this.AllowRoute && waitCreateChannel.Route) |                             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; |                                         return true; | ||||||
|                                     } |                                     } | ||||||
|                                     else |                                     else | ||||||
| @@ -593,7 +661,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             waitCreateChannel.SwitchId(); |                             waitCreateChannel.SwitchId(); | ||||||
|                             byteBlock.Reset(); |                             byteBlock.Reset(); | ||||||
|                             waitCreateChannel.Package(byteBlock); |                             waitCreateChannel.Package(byteBlock); | ||||||
|                             this.Send(P8_CreateChannel_Response, byteBlock); |                             await this.SendAsync(P8_CreateChannel_Response, byteBlock).ConfigureFalseAwait(); | ||||||
|                         } |                         } | ||||||
|                         catch (Exception ex) |                         catch (Exception ex) | ||||||
|                         { |                         { | ||||||
| @@ -609,9 +677,9 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             waitCreateChannel.UnpackageRouter(byteBlock); |                             waitCreateChannel.UnpackageRouter(byteBlock); | ||||||
|                             if (this.AllowRoute && waitCreateChannel.Route) |                             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; |                                     return true; | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
| @@ -635,9 +703,9 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                             channelPackage.UnpackageRouter(byteBlock); |                             channelPackage.UnpackageRouter(byteBlock); | ||||||
|                             if (this.AllowRoute && channelPackage.Route) |                             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 |                                 else | ||||||
|                                 { |                                 { | ||||||
| @@ -648,7 +716,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                                     channelPackage.DataType = ChannelDataType.DisposeOrder; |                                     channelPackage.DataType = ChannelDataType.DisposeOrder; | ||||||
|                                     byteBlock.Reset(); |                                     byteBlock.Reset(); | ||||||
|                                     channelPackage.Package(byteBlock); |                                     channelPackage.Package(byteBlock); | ||||||
|                                     this.Send(P9_ChannelPackage, byteBlock); |                                     await this.SendAsync(P9_ChannelPackage, byteBlock).ConfigureFalseAwait(); | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                             else |                             else | ||||||
| @@ -683,7 +751,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public virtual bool Ping(string targetId, int timeout = 5000) |         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); |                 return actor.Ping(timeout); | ||||||
|             } |             } | ||||||
| @@ -697,15 +765,15 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <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 |             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) |                         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; |                             this.Id = id; | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
| @@ -754,13 +822,13 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|             this.SendJsonObject(P3_ResetId_Request, waitSetId); |             this.SendJsonObject(P3_ResetId_Request, waitSetId); | ||||||
|  |  | ||||||
|             switch (await waitData.WaitAsync(5000)) |             switch (await waitData.WaitAsync(5000).ConfigureFalseAwait()) | ||||||
|             { |             { | ||||||
|                 case WaitDataStatus.SetRunning: |                 case WaitDataStatus.SetRunning: | ||||||
|                     { |                     { | ||||||
|                         if (waitData.WaitResult.Status == 1) |                         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; |                             this.Id = id; | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
| @@ -801,6 +869,17 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             this.Send(protocol, bytes, 0, bytes.Length); |             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) |         private T ResolveJsonObject<T>(string json) | ||||||
|         { |         { | ||||||
| #if NET6_0_OR_GREATER | #if NET6_0_OR_GREATER | ||||||
| @@ -836,31 +915,34 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public virtual bool TryFindDmtpActor(string targetId, out DmtpActor actor) |         public virtual async Task<DmtpActor> TryFindDmtpActor(string targetId) | ||||||
|         { |         { | ||||||
|             if (targetId == this.Id) |             if (targetId == this.Id) | ||||||
|             { |             { | ||||||
|                 actor = this; |                 return this; | ||||||
|                 return true; |  | ||||||
|             } |             } | ||||||
|             if (this.OnFindDmtpActor?.Invoke(targetId) is DmtpActor newActor) |             if (this.FindDmtpActor != null) | ||||||
|             { |             { | ||||||
|                 actor = newActor; |                 if (await this.FindDmtpActor.Invoke(targetId).ConfigureFalseAwait() is DmtpActor newActor) | ||||||
|                 return true; |                 { | ||||||
|  |                     return newActor; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             actor = default; |             return default; | ||||||
|             return false; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public virtual bool TryRoute(RouteType routerType, RouterPackage routerPackage) |         public virtual async Task<bool> TryRoute(PackageRouterEventArgs e) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var args = new PackageRouterEventArgs(routerType, routerPackage); |                 if (this.Routing != null) | ||||||
|                 this.OnRouting?.Invoke(this, args); |                 { | ||||||
|                 return args.IsPermitOperation; |                     await this.Routing.Invoke(this, e).ConfigureFalseAwait(); | ||||||
|  |                     return e.IsPermitOperation; | ||||||
|  |                 } | ||||||
|  |                 return false; | ||||||
|             } |             } | ||||||
|             catch |             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) |         private bool PrivatePing(string targetId, int timeout) | ||||||
|         { |         { | ||||||
|             var waitPing = new WaitPing |             var waitPing = new WaitPing | ||||||
| @@ -942,7 +1003,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 this.SendJsonObject(P5_Ping_Request, waitPing); |                 this.SendJsonObject(P5_Ping_Request, waitPing); | ||||||
|                 switch (await waitData.WaitAsync(timeout)) |                 switch (await waitData.WaitAsync(timeout).ConfigureFalseAwait()) | ||||||
|                 { |                 { | ||||||
|                     case WaitDataStatus.SetRunning: |                     case WaitDataStatus.SetRunning: | ||||||
|                         { |                         { | ||||||
| @@ -971,7 +1032,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region 重写 |         #region 断开 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
| @@ -979,19 +1040,36 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <param name="disposing"></param> |         /// <param name="disposing"></param> | ||||||
|         protected override void Dispose(bool disposing) |         protected override void Dispose(bool disposing) | ||||||
|         { |         { | ||||||
|             this.OnClose = null; |             this.Closed = null; | ||||||
|             this.OnRouting = null; |             this.Routing = null; | ||||||
|             this.OnFindDmtpActor = null; |             this.FindDmtpActor = null; | ||||||
|             this.OnHandshaked = null; |             this.Handshaked = null; | ||||||
|             this.OnHandshaking = null; |             this.Handshaking = null; | ||||||
|             this.OnResetId = null; |             this.IdChanged = null; | ||||||
|  |  | ||||||
|             this.OutputSend = null; |             this.OutputSend = null; | ||||||
|  |             this.OnClosed(true, nameof(Dispose)); | ||||||
|             this.WaitHandlePool.SafeDispose(); |             this.WaitHandlePool.SafeDispose(); | ||||||
|             this.Close(false, nameof(Dispose)); |  | ||||||
|             base.Dispose(disposing); |             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 重写 |         #endregion 重写 | ||||||
|  |  | ||||||
|         #region 协议同步发送 |         #region 协议同步发送 | ||||||
| @@ -1005,7 +1083,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(length)), |             new ArraySegment<byte>(TouchSocketBitConverter.BigEndian.GetBytes(length)), | ||||||
|             new ArraySegment<byte>(buffer,offset,length) |             new ArraySegment<byte>(buffer,offset,length) | ||||||
|            }; |            }; | ||||||
|             this.OutputSend?.Invoke(this, transferBytes); |             this.OutputSend.Invoke(this, transferBytes); | ||||||
|             this.LastActiveTime = DateTime.Now; |             this.LastActiveTime = DateTime.Now; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1022,10 +1100,20 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public virtual Task SendAsync(ushort protocol, byte[] buffer, int offset, int length) |         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 协议异步发送 |         #endregion 协议异步发送 | ||||||
| @@ -1059,7 +1147,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             { |             { | ||||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); |                 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); |                 return actor.CreateChannel(id, metadata); | ||||||
|             } |             } | ||||||
| @@ -1077,7 +1165,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); |                 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); |                 return actor.CreateChannel(metadata); | ||||||
|             } |             } | ||||||
| @@ -1100,37 +1188,37 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <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)) |             if (string.IsNullOrEmpty(targetId)) | ||||||
|             { |             { | ||||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(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 |             else | ||||||
|             { |             { | ||||||
|                 return this.PrivateCreateChannelAsync(targetId, false, id, metadata); |                 return await this.PrivateCreateChannelAsync(targetId, false, id, metadata).ConfigureFalseAwait(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <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)) |             if (string.IsNullOrEmpty(targetId)) | ||||||
|             { |             { | ||||||
|                 throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(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 |             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); |                                         var channel = new InternalChannel(this, targetId, result.Metadata); | ||||||
|                                         channel.SetId(result.ChannelId); |                                         channel.SetId(result.ChannelId); | ||||||
|                                         channel.SetUsing(); |                                         channel.SetUsing(); | ||||||
|                                         return this.m_userChannels.TryAdd(result.ChannelId, channel) |                                         if (this.m_userChannels.TryAdd(result.ChannelId, channel)) | ||||||
|                                             ? (IDmtpChannel)channel |                                         { | ||||||
|                                             : throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); |                                             return channel; | ||||||
|  |                                         } | ||||||
|  |                                         else | ||||||
|  |                                         { | ||||||
|  |                                             throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); | ||||||
|  |                                         } | ||||||
|                                     } |                                     } | ||||||
|                                 case TouchSocketDmtpStatus.ClientNotFind: |                                 case TouchSocketDmtpStatus.ClientNotFind: | ||||||
|                                     { |                                     { | ||||||
| @@ -1269,8 +1362,8 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 waitCreateChannel.Package(byteBlock); |                 waitCreateChannel.Package(byteBlock); | ||||||
|                 this.Send(P7_CreateChannel_Request, byteBlock); |                 await this.SendAsync(P7_CreateChannel_Request, byteBlock).ConfigureFalseAwait(); | ||||||
|                 switch (await waitData.WaitAsync(10 * 1000)) |                 switch (await waitData.WaitAsync(10 * 1000).ConfigureFalseAwait()) | ||||||
|                 { |                 { | ||||||
|                     case WaitDataStatus.SetRunning: |                     case WaitDataStatus.SetRunning: | ||||||
|                         { |                         { | ||||||
| @@ -1282,9 +1375,14 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                                         var channel = new InternalChannel(this, targetId, result.Metadata); |                                         var channel = new InternalChannel(this, targetId, result.Metadata); | ||||||
|                                         channel.SetId(result.ChannelId); |                                         channel.SetId(result.ChannelId); | ||||||
|                                         channel.SetUsing(); |                                         channel.SetUsing(); | ||||||
|                                         return this.m_userChannels.TryAdd(result.ChannelId, channel) |                                         if (this.m_userChannels.TryAdd(result.ChannelId, channel)) | ||||||
|                                             ? (IDmtpChannel)channel |                                         { | ||||||
|                                             : throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); |                                             return channel; | ||||||
|  |                                         } | ||||||
|  |                                         else | ||||||
|  |                                         { | ||||||
|  |                                             throw new Exception(TouchSocketDmtpStatus.UnknownError.GetDescription()); | ||||||
|  |                                         } | ||||||
|                                     } |                                     } | ||||||
|                                 case TouchSocketDmtpStatus.ClientNotFind: |                                 case TouchSocketDmtpStatus.ClientNotFind: | ||||||
|                                     { |                                     { | ||||||
| @@ -1333,7 +1431,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 channel.SetId(id); |                 channel.SetId(id); | ||||||
|                 if (this.m_userChannels.TryAdd(id, channel)) |                 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; |                     return true; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
| @@ -1344,16 +1442,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ThisRequestCreateChannel(object state) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 this.OnCreateChannel?.Invoke(this, (CreateChannelEventArgs)state); |  | ||||||
|             } |  | ||||||
|             catch |  | ||||||
|             { |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         #endregion IDmtpChannel |         #endregion IDmtpChannel | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 提供Dmtp协议的最基础功能件 |     /// 提供Dmtp协议的最基础功能件 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public interface IDmtpActor : IDependencyObject |     public interface IDmtpActor : IDependencyObject, IHandshakeObject | ||||||
|     { |     { | ||||||
|         #region 属性 |         #region 属性 | ||||||
|  |  | ||||||
| @@ -39,11 +39,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         string Id { get; } |         string Id { get; } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 获取当前功能件是否已经完成握手连接状态。 |  | ||||||
|         /// </summary> |  | ||||||
|         bool IsHandshaked { get; } |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 最后一次活动时间。 |         /// 最后一次活动时间。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -152,9 +147,8 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 关闭 |         /// 关闭 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="sendClose">是否发送close报文</param> |  | ||||||
|         /// <param name="message">传递消息</param> |         /// <param name="message">传递消息</param> | ||||||
|         void Close(bool sendClose, string message); |         void Close(string message); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 向当前对点发送一个Ping报文,并且等待回应。 |         /// 向当前对点发送一个Ping报文,并且等待回应。 | ||||||
| @@ -226,6 +220,14 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <param name="length"></param> |         /// <param name="length"></param> | ||||||
|         Task SendAsync(ushort protocol, byte[] buffer, int offset, int length); |         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> |         /// <summary> | ||||||
|         /// 以Fast序列化,发送小(64K)对象。接收方需要使用ReadObject读取对象。 |         /// 以Fast序列化,发送小(64K)对象。接收方需要使用ReadObject读取对象。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -260,25 +262,20 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 尝试获取指定Id的DmtpActor。一般此方法仅在Service下有效。 |         /// 尝试获取指定Id的DmtpActor。一般此方法仅在Service下有效。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="targetId"></param> |         /// <param name="targetId"></param> | ||||||
|         /// <param name="actor"></param> |  | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         bool TryFindDmtpActor(string targetId, out DmtpActor actor); |         Task<DmtpActor> TryFindDmtpActor(string targetId); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 尝试请求路由,触发路由相关插件。 |         /// 尝试请求路由,触发路由相关插件。并在路由失败时向<see cref="MsgPermitEventArgs.Message"/>中传递消息。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="routerType"></param> |  | ||||||
|         /// <param name="routerPackage"></param> |  | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         bool TryRoute(RouteType routerType, RouterPackage routerPackage); |         Task<bool> TryRoute(PackageRouterEventArgs e); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 尝试请求路由,触发路由相关插件。并在路由失败时向<see cref="MsgRouterPackage.Message"/>中传递消息。 |         /// 发送Close请求 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="routerType"></param> |         /// <param name="msg"></param> | ||||||
|         /// <param name="routerPackage"></param> |         bool SendClose(string msg); | ||||||
|         /// <returns></returns> |  | ||||||
|         bool TryRoute(RouteType routerType, WaitRouterPackage routerPackage); |  | ||||||
|  |  | ||||||
|         #endregion 方法 |         #endregion 方法 | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -17,17 +17,22 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class TcpDmtpAdapter : CustomFixedHeaderByteBlockDataHandlingAdapter<DmtpMessage> |     public class TcpDmtpAdapter : CustomFixedHeaderByteBlockDataHandlingAdapter<DmtpMessage> | ||||||
|     { |     { | ||||||
|         private SpinLock m_locker = new SpinLock(); |         private readonly SemaphoreSlim m_locker = new SemaphoreSlim(1, 1); | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public override bool CanSendRequestInfo => true; |         public override bool CanSendRequestInfo => true; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public override bool CanSplicingSend => false; |         public override bool CanSplicingSend => true; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public override int HeaderLength => 6; |         public override int HeaderLength => 6; | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 最大拼接 | ||||||
|  |         /// </summary> | ||||||
|  |         public const int MaxSplicing = 1024 * 64; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override DmtpMessage GetInstance() |         protected override DmtpMessage GetInstance() | ||||||
|         { |         { | ||||||
| @@ -40,6 +45,25 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             request.SafeDispose(); |             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/> |         /// <inheritdoc/> | ||||||
|         protected override void PreviewSend(IRequestInfo requestInfo) |         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/> |         /// <inheritdoc/> | ||||||
|         protected override void PreviewSend(IList<ArraySegment<byte>> transferBytes) |         protected override void PreviewSend(IList<ArraySegment<byte>> transferBytes) | ||||||
|         { |         { | ||||||
| @@ -77,20 +149,31 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送"); |                 throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送"); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var lockTaken = false; |             if (length > this.MaxPackageSize) | ||||||
|             try |  | ||||||
|             { |             { | ||||||
|                 this.m_locker.Enter(ref lockTaken); |                 try | ||||||
|                 foreach (var item in transferBytes) |  | ||||||
|                 { |                 { | ||||||
|                     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); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -0,0 +1,56 @@ | |||||||
|  | #region copyright | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||||
|  | //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||||
|  | //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||||
|  | //  使用文档:https://diego2098.gitee.io/thingsgateway-docs/ | ||||||
|  | //  QQ群:605534569 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | #endregion | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 | ||||||
|  | //  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 | ||||||
|  | //  CSDN博客:https://blog.csdn.net/qq_40374647 | ||||||
|  | //  哔哩哔哩视频:https://space.bilibili.com/94253567 | ||||||
|  | //  Gitee源代码仓库:https://gitee.com/RRQM_Home | ||||||
|  | //  Github源代码仓库:https://github.com/RRQM | ||||||
|  | //  API首页:http://rrqm_home.gitee.io/touchsocket/ | ||||||
|  | //  交流QQ群:234762506 | ||||||
|  | //  感谢您的下载和使用 | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Dmtp | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 针对Dmtp的配置项 | ||||||
|  |     /// </summary> | ||||||
|  |     public class DmtpOption | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 连接令箭 | ||||||
|  |         /// </summary> | ||||||
|  |         public string VerifyToken { get; set; } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 连接时指定Id。 | ||||||
|  |         /// <para> | ||||||
|  |         /// 使用该功能时,仅在服务器的Handshaking之后生效。且如果id重复,则会连接失败。 | ||||||
|  |         /// </para> | ||||||
|  |         /// </summary> | ||||||
|  |         public string Id { get; set; } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置DmtpClient连接时的元数据 | ||||||
|  |         /// </summary> | ||||||
|  |         public Metadata Metadata { get; set; } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 验证连接超时时间。仅用于服务器。意为:当服务器收到基础链接,在指定的时间内如果没有收到握手信息,则直接视为无效链接,直接断开。 | ||||||
|  |         /// </summary> | ||||||
|  |         public TimeSpan VerifyTimeout { get; set; } = TimeSpan.FromSeconds(3); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -70,7 +70,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 最大传输速度。 |         /// 最大传输速度。 | ||||||
|         /// </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> |         /// <summary> | ||||||
|         /// 元数据 |         /// 元数据 | ||||||
|   | |||||||
| @@ -33,117 +33,40 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         #region 字段 |         #region 字段 | ||||||
|  |  | ||||||
|         private bool m_allowRoute; |         private bool m_allowRoute; | ||||||
|         private Func<string, IDmtpActor> m_findDmtpActor; |         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||||
|         private DmtpActor m_smtpActor; |         private DmtpActor m_dmtpActor; | ||||||
|         private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); |         private readonly SemaphoreSlim m_semaphoreForConnect = new SemaphoreSlim(1, 1); | ||||||
|         #endregion 字段 |         #endregion 字段 | ||||||
|  |  | ||||||
|         /// <inheritdoc cref="IDmtpActor.Id"/> |         /// <inheritdoc cref="IDmtpActor.Id"/> | ||||||
|         public string Id => this.DmtpActor.Id; |         public string Id => this.m_dmtpActor.Id; | ||||||
|  |  | ||||||
|         /// <inheritdoc cref="IDmtpActor.IsHandshaked"/> |         /// <inheritdoc cref="IHandshakeObject.IsHandshaked"/> | ||||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; |         public bool IsHandshaked => this.m_dmtpActor != null && this.m_dmtpActor.IsHandshaked; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } |         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||||
|  |  | ||||||
|         #region 连接 |         #region 连接 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 建立Tcp连接,并且执行握手。 |         /// 使用基于Http升级的协议,连接Dmtp服务器 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="timeout"></param> |         /// <param name="timeout"></param> | ||||||
|         /// <returns></returns> |         /// <param name="token"></param> | ||||||
|         /// <exception cref="Exception"></exception> |         /// <exception cref="Exception"></exception> | ||||||
|         public override ITcpClient Connect(int timeout = 5000) |         public override void Connect(int timeout, CancellationToken token) | ||||||
|         { |  | ||||||
|             lock (this.SyncRoot) |  | ||||||
|             { |  | ||||||
|                 if (this.IsHandshaked) |  | ||||||
|                 { |  | ||||||
|                     return this; |  | ||||||
|                 } |  | ||||||
|                 if (!this.Online) |  | ||||||
|                 { |  | ||||||
|                     base.Connect(timeout); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 var request = new HttpRequest() |  | ||||||
|                     .SetHost(this.RemoteIPHost.Host); |  | ||||||
|                 request.Headers.Add(HttpHeaders.Connection, "upgrade"); |  | ||||||
|                 request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower()); |  | ||||||
|  |  | ||||||
|                 request.AsMethod(DmtpUtility.Dmtp); |  | ||||||
|                 var response = this.RequestContent(request); |  | ||||||
|                 if (response.StatusCode == 101) |  | ||||||
|                 { |  | ||||||
|                     this.SwitchProtocolToDmtp(); |  | ||||||
|                     this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |  | ||||||
|                         this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), |  | ||||||
|                         timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); |  | ||||||
|                     return this; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     throw new Exception(response.StatusMessage); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public virtual IHttpDmtpClient Connect(CancellationToken token, int timeout = 5000) |  | ||||||
|         { |  | ||||||
|             lock (this.SyncRoot) |  | ||||||
|             { |  | ||||||
|                 if (this.IsHandshaked) |  | ||||||
|                 { |  | ||||||
|                     return this; |  | ||||||
|                 } |  | ||||||
|                 if (!this.Online) |  | ||||||
|                 { |  | ||||||
|                     base.Connect(timeout); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 var request = new HttpRequest() |  | ||||||
|                     .SetHost(this.RemoteIPHost.Host); |  | ||||||
|                 request.Headers.Add(HttpHeaders.Connection, "upgrade"); |  | ||||||
|                 request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower()); |  | ||||||
|  |  | ||||||
|                 request.AsMethod(DmtpUtility.Dmtp); |  | ||||||
|                 var response = this.RequestContent(request, timeout: timeout, token: token); |  | ||||||
|                 if (response.StatusCode == 101) |  | ||||||
|                 { |  | ||||||
|                     this.SwitchProtocolToDmtp(); |  | ||||||
|                     this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |  | ||||||
|                         this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), |  | ||||||
|                         timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); |  | ||||||
|                     return this; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     throw new Exception(response.StatusMessage); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 建立Tcp连接,并且执行握手。 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="timeout"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         /// <exception cref="Exception"></exception> |  | ||||||
|         public override async Task<ITcpClient> ConnectAsync(int timeout = 5000) |  | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 await this.m_semaphore.WaitAsync(); |                 this.m_semaphoreForConnect.Wait(token); | ||||||
|                 if (this.IsHandshaked) |                 if (this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
|                     return this; |                     return; | ||||||
|                 } |                 } | ||||||
|                 if (!this.Online) |                 if (!this.Online) | ||||||
|                 { |                 { | ||||||
|                     await base.ConnectAsync(timeout); |                     base.Connect(timeout, token); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 var request = new HttpRequest() |                 var request = new HttpRequest() | ||||||
| @@ -156,10 +79,10 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 if (response.StatusCode == 101) |                 if (response.StatusCode == 101) | ||||||
|                 { |                 { | ||||||
|                     this.SwitchProtocolToDmtp(); |                     this.SwitchProtocolToDmtp(); | ||||||
|                     await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |                     this.m_dmtpActor.Handshake( | ||||||
|                          this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), |  | ||||||
|                          timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); |                         this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Id, timeout, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Metadata, token); | ||||||
|                     return this; |                     return; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
| @@ -168,19 +91,25 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|                 this.m_semaphore.Release(); |                 this.m_semaphoreForConnect.Release(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <summary> | ||||||
|         public virtual async Task<IHttpDmtpClient> ConnectAsync(CancellationToken token, int timeout = 5000) |         /// 异步使用基于Http升级的协议,连接Dmtp服务器 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="timeout"></param> | ||||||
|  |         /// <param name="token"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         /// <exception cref="Exception"></exception> | ||||||
|  |         public override async Task ConnectAsync(int timeout, CancellationToken token) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 await this.m_semaphore.WaitAsync(); |                 await this.m_semaphoreForConnect.WaitAsync(timeout, token); | ||||||
|                 if (this.IsHandshaked) |                 if (this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
|                     return this; |                     return; | ||||||
|                 } |                 } | ||||||
|                 if (!this.Online) |                 if (!this.Online) | ||||||
|                 { |                 { | ||||||
| @@ -193,14 +122,12 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower()); |                 request.Headers.Add(HttpHeaders.Upgrade, DmtpUtility.Dmtp.ToLower()); | ||||||
|  |  | ||||||
|                 request.AsMethod(DmtpUtility.Dmtp); |                 request.AsMethod(DmtpUtility.Dmtp); | ||||||
|                 var response = this.RequestContent(request, timeout: timeout, token: token); |                 var response = await this.RequestContentAsync(request); | ||||||
|                 if (response.StatusCode == 101) |                 if (response.StatusCode == 101) | ||||||
|                 { |                 { | ||||||
|                     this.SwitchProtocolToDmtp(); |                     this.SwitchProtocolToDmtp(); | ||||||
|                     await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |                     await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Id, timeout, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Metadata, token); | ||||||
|                          this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), |                     return; | ||||||
|                          timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); |  | ||||||
|                     return this; |  | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
| @@ -209,25 +136,53 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|                 this.m_semaphore.Release(); |                 this.m_semaphoreForConnect.Release(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion 连接 |         #endregion 连接 | ||||||
|  |  | ||||||
|  |         #region 断开 | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override void Dispose(bool disposing) |         protected override void Dispose(bool disposing) | ||||||
|         { |         { | ||||||
|             this.DmtpActor.SafeDispose(); |             if (this.IsHandshaked) | ||||||
|  |             { | ||||||
|  |                 this.m_dmtpActor?.SafeDispose(); | ||||||
|  |             } | ||||||
|             base.Dispose(disposing); |             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/> |         /// <inheritdoc/> | ||||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) |         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||||
|         { |         { | ||||||
|             if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message) |             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) |                     if (this.PluginsManager.Enable) | ||||||
|                     { |                     { | ||||||
| @@ -250,25 +205,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 |         #region ResetId | ||||||
|  |  | ||||||
|         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> |         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||||
|         public void ResetId(string id) |         public void ResetId(string id) | ||||||
|         { |         { | ||||||
|             this.m_smtpActor.ResetId(id); |             this.m_dmtpActor.ResetId(id); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> |         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||||
|         public Task ResetIdAsync(string newId) |         public Task ResetIdAsync(string newId) | ||||||
|         { |         { | ||||||
|             return this.m_smtpActor.ResetIdAsync(newId); |             return this.m_dmtpActor.ResetIdAsync(newId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion ResetId |         #endregion ResetId | ||||||
| @@ -277,72 +226,47 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         { |         { | ||||||
|             this.Protocol = DmtpUtility.DmtpProtocol; |             this.Protocol = DmtpUtility.DmtpProtocol; | ||||||
|             this.SetDataHandlingAdapter(new TcpDmtpAdapter()); |             this.SetDataHandlingAdapter(new TcpDmtpAdapter()); | ||||||
|             this.m_smtpActor = new SealedDmtpActor(this.m_allowRoute) |             this.m_dmtpActor = new SealedDmtpActor(this.m_allowRoute) | ||||||
|             { |             { | ||||||
|                 OutputSend = DmtpActorSend, |                 OutputSend = this.DmtpActorSend, | ||||||
|                 OnRouting = OnDmtpActorRouting, |                 OutputSendAsync = this.DmtpActorSendAsync, | ||||||
|                 OnHandshaking = this.OnDmtpActorHandshaking, |                 Routing = this.OnDmtpActorRouting, | ||||||
|                 OnHandshaked = OnDmtpActorHandshaked, |                 Handshaking = this.OnDmtpActorHandshaking, | ||||||
|                 OnClose = OnDmtpActorClose, |                 Handshaked = this.OnDmtpActorHandshaked, | ||||||
|                 OnCreateChannel = this.OnDmtpActorCreateChannel, |                 Closed = this.OnDmtpActorClose, | ||||||
|  |                 CreatedChannel = this.OnDmtpActorCreateChannel, | ||||||
|                 Logger = this.Logger, |                 Logger = this.Logger, | ||||||
|                 Client = this, |                 Client = this, | ||||||
|                 OnFindDmtpActor = this.m_findDmtpActor |                 FindDmtpActor = this.m_findDmtpActor | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region 内部委托绑定 |         #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); |             return this.OnCreateChannel(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaked(e); |             return this.OnHandshaked(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaking(e); |             return this.OnHandshaking(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) |         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnRouting(e); |             return this.OnRouting(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) |         private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||||
| @@ -350,6 +274,11 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             base.Send(transferBytes); |             base.Send(transferBytes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private Task DmtpActorSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||||
|  |         { | ||||||
|  |             return base.SendAsync(transferBytes); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         #endregion 内部委托绑定 |         #endregion 内部委托绑定 | ||||||
|  |  | ||||||
|         #region 事件触发 |         #region 事件触发 | ||||||
| @@ -358,32 +287,53 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 当创建通道 |         /// 当创建通道 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在完成握手连接时 |         /// 在完成握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 即将握手连接时 |         /// 即将握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e">参数</param> |         /// <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> | ||||||
|         /// 当需要转发路由包时 |         /// 当需要转发路由包时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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 事件触发 |         #endregion 事件触发 | ||||||
|   | |||||||
| @@ -41,12 +41,12 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 连接令箭 |         /// 连接令箭 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty); |         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken; | ||||||
|  |  | ||||||
|         #region 字段 |         #region 字段 | ||||||
|  |  | ||||||
|         private bool m_allowRoute; |         private bool m_allowRoute; | ||||||
|         private Func<string, IDmtpActor> m_findDmtpActor; |         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||||
|  |  | ||||||
|         #endregion 字段 |         #endregion 字段 | ||||||
|  |  | ||||||
| @@ -68,17 +68,28 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             await base.OnConnected(socketClient, e); |             await base.OnConnected(socketClient, e); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private IDmtpActor OnServiceFindDmtpActor(string id) |  | ||||||
|         { |  | ||||||
|             return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private DmtpActor PrivateOnRpcActorInit() |         private DmtpActor PrivateOnRpcActorInit() | ||||||
|         { |         { | ||||||
|             return new SealedDmtpActor(this.m_allowRoute) |             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,115 +31,85 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     public class HttpDmtpSocketClient : HttpSocketClient, IHttpDmtpSocketClient |     public class HttpDmtpSocketClient : HttpSocketClient, IHttpDmtpSocketClient | ||||||
|     { |     { | ||||||
|         internal Func<DmtpActor> m_internalOnRpcActorInit; |         internal Func<DmtpActor> m_internalOnRpcActorInit; | ||||||
|         private DmtpActor m_smtpActor; |         private DmtpActor m_dmtpActor; | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; |         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 验证超时时间,默认为3000ms |         /// 验证超时时间 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public int VerifyTimeout => this.Config.GetValue(DmtpConfigExtension.VerifyTimeoutProperty); |         public TimeSpan VerifyTimeout => this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyTimeout; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 连接令箭 |         /// 连接令箭 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty); |         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken; | ||||||
|  |  | ||||||
|  |         #region 断开 | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public override void Close(string msg = "") |         public override void Close(string msg = "") | ||||||
|         { |         { | ||||||
|             if (this.m_smtpActor == null) |             if (this.m_dmtpActor != null) | ||||||
|             { |             { | ||||||
|                 base.Close(msg); |                 this.m_dmtpActor.SendClose(msg); | ||||||
|                 return; |                 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> |         /// <summary> | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="disposing"></param> |         /// <param name="disposing"></param> | ||||||
|         protected override void Dispose(bool disposing) |         protected override void Dispose(bool disposing) | ||||||
|         { |         { | ||||||
|             this.DmtpActor?.SafeDispose(); |             this.m_dmtpActor?.SafeDispose(); | ||||||
|             base.Dispose(disposing); |             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> |         /// <summary> | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <param name="e"></param> | ||||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) |         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||||
|         { |         { | ||||||
|             this.DmtpActor?.Close(false, e.Message); |             this.m_dmtpActor?.Close(e.Message); | ||||||
|             await base.OnDisconnected(e); |             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> |         /// <summary> | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -158,66 +128,73 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             await base.OnReceivedHttpRequest(request); |             await base.OnReceivedHttpRequest(request); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||||
|  |         { | ||||||
|  |             if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message) | ||||||
|  |             { | ||||||
|  |                 if (!await this.m_dmtpActor.InputReceivedData(message)) | ||||||
|  |                 { | ||||||
|  |                     await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             await base.ReceivedData(e); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task OnDmtpIdChanged(DmtpActor actor, IdChangedEventArgs e) | ||||||
|  |         { | ||||||
|  |             this.DirectResetId(e.NewId); | ||||||
|  |             return EasyTask.CompletedTask; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         private void SetRpcActor(DmtpActor actor) |         private void SetRpcActor(DmtpActor actor) | ||||||
|         { |         { | ||||||
|             actor.Id = this.Id; |             actor.Id = this.Id; | ||||||
|             actor.OnResetId = this.ThisOnResetId; |             actor.IdChanged = this.OnDmtpIdChanged; | ||||||
|  |             actor.OutputSendAsync = this.ThisDmtpActorOutputSendAsync; | ||||||
|             actor.OutputSend = this.ThisDmtpActorOutputSend; |             actor.OutputSend = this.ThisDmtpActorOutputSend; | ||||||
|             actor.Client = this; |             actor.Client = this; | ||||||
|             actor.OnClose = this.OnDmtpActorClose; |             actor.Closed = this.OnDmtpActorClose; | ||||||
|             actor.OnRouting = this.OnDmtpActorRouting; |             actor.Routing = this.OnDmtpActorRouting; | ||||||
|             actor.OnHandshaked = this.OnDmtpActorHandshaked; |             actor.Handshaked = this.OnDmtpActorHandshaked; | ||||||
|             actor.OnHandshaking = this.OnDmtpActorHandshaking; |             actor.Handshaking = this.OnDmtpActorHandshaking; | ||||||
|             actor.OnCreateChannel = this.OnDmtpActorCreateChannel; |             actor.CreatedChannel = this.OnDmtpActorCreatedChannel; | ||||||
|             actor.Logger = this.Logger; |             actor.Logger = this.Logger; | ||||||
|             this.m_smtpActor = actor; |             this.m_dmtpActor = actor; | ||||||
|  |  | ||||||
|             this.Protocol = DmtpUtility.DmtpProtocol; |             this.Protocol = DmtpUtility.DmtpProtocol; | ||||||
|             this.SetDataHandlingAdapter(new TcpDmtpAdapter()); |             this.SetDataHandlingAdapter(new TcpDmtpAdapter()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ThisOnResetId(DmtpActor actor, WaitSetId waitSetId) |  | ||||||
|         { |  | ||||||
|             this.DirectResetId(waitSetId.NewId); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) |         private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||||
|         { |         { | ||||||
|             base.Send(transferBytes); |             base.Send(transferBytes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private Task ThisDmtpActorOutputSendAsync(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||||
|  |         { | ||||||
|  |             return base.SendAsync(transferBytes); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         #region 内部委托绑定 |         #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); |             return this.OnCreatedChannel(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaked(e); |             return this.OnHandshaked(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             if (e.Token == this.VerifyToken) |             if (e.Token == this.VerifyToken) | ||||||
|             { |             { | ||||||
| @@ -228,25 +205,12 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 e.Message = "Token不受理"; |                 e.Message = "Token不受理"; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             this.OnHandshaking(e); |             return this.OnHandshaking(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) |         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnRouting(e); |             return this.OnRouting(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion 内部委托绑定 |         #endregion 内部委托绑定 | ||||||
| @@ -257,32 +221,53 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 当创建通道 |         /// 当创建通道 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在完成握手连接时 |         /// 在完成握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在验证Token时 |         /// 在验证Token时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e">参数</param> |         /// <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> | ||||||
|         /// 在需要转发路由包时。 |         /// 在需要转发路由包时。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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 事件 |         #endregion 事件 | ||||||
|   | |||||||
| @@ -17,20 +17,5 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public interface IHttpDmtpClient : IHttpClient, IHttpDmtpClientBase |     public interface IHttpDmtpClient : IHttpClient, IHttpDmtpClientBase | ||||||
|     { |     { | ||||||
|         /// <summary> |  | ||||||
|         /// 建立Tcp,并发送Http请求,最后完成Dmtp握手连接。 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="token"></param> |  | ||||||
|         /// <param name="timeout"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         IHttpDmtpClient Connect(CancellationToken token, int timeout = 5000); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 建立Tcp,并发送Http请求,最后完成Dmtp握手连接。 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="token"></param> |  | ||||||
|         /// <param name="timeout"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         Task<IHttpDmtpClient> ConnectAsync(CancellationToken token, int timeout = 5000); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -17,20 +17,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public interface ITcpDmtpClient : ITcpDmtpClientBase, ITcpClient |     public interface ITcpDmtpClient : ITcpDmtpClientBase, ITcpClient | ||||||
|     { |     { | ||||||
|         /// <summary> |  | ||||||
|         /// 建立Tcp连接,并且执行握手。 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="token">可取消令箭</param> |  | ||||||
|         /// <param name="timeout">超时时间</param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         ITcpDmtpClient Connect(CancellationToken token, int timeout = 5000); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 建立Tcp连接,并且执行握手。 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="token">可取消令箭</param> |  | ||||||
|         /// <param name="timeout">超时时间</param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         Task<ITcpDmtpClient> ConnectAsync(CancellationToken token, int timeout = 5000); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -39,22 +39,24 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } |         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||||
|  |  | ||||||
|         /// <inheritdoc cref="IDmtpActor.Id"/> |         /// <inheritdoc cref="IDmtpActor.Id"/> | ||||||
|         public string Id => this.DmtpActor.Id; |         public string Id => this.m_dmtpActor.Id; | ||||||
|  |  | ||||||
|         #region 字段 |         #region 字段 | ||||||
|  |  | ||||||
|         private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); |         private readonly SemaphoreSlim m_semaphoreForConnect = new SemaphoreSlim(1, 1); | ||||||
|         private bool m_allowRoute; |         private bool m_allowRoute; | ||||||
|         private Func<string, IDmtpActor> m_findDmtpActor; |         private SealedDmtpActor m_dmtpActor; | ||||||
|         private SealedDmtpActor m_smtpActor; |         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||||
|  |  | ||||||
|         #endregion 字段 |         #endregion 字段 | ||||||
|  |  | ||||||
|         /// <inheritdoc cref="IDmtpActor.IsHandshaked"/> |         /// <inheritdoc cref="IHandshakeObject.IsHandshaked"/> | ||||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; |         public bool IsHandshaked => this.m_dmtpActor != null && this.m_dmtpActor.IsHandshaked; | ||||||
|  |  | ||||||
|  |         #region 断开 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 发送<see cref="IDmtpActor"/>关闭消息。 |         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||||
| @@ -63,107 +65,90 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public override void Close(string msg = "") |         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); |             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 连接 |         #region 连接 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 建立Tcp连接,并且执行握手。 |         /// 进行Dmtp协议的握手连接 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="timeout"></param> |         /// <param name="timeout"></param> | ||||||
|  |         /// <param name="token"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public override ITcpClient Connect(int timeout = 5000) |         public override void Connect(int timeout, CancellationToken token) | ||||||
|         { |         { | ||||||
|             lock (this.SyncRoot) |             try | ||||||
|             { |             { | ||||||
|  |                 this.m_semaphoreForConnect.Wait(token); | ||||||
|                 if (this.IsHandshaked) |                 if (this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
|                     return this; |                     return; | ||||||
|                 } |                 } | ||||||
|                 if (!this.Online) |                 if (!this.Online) | ||||||
|                 { |                 { | ||||||
|                     base.Connect(timeout); |                     base.Connect(timeout, token); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |                 this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken, | ||||||
|                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); |                     this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Id, timeout, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Metadata, token); | ||||||
|                 return this; |  | ||||||
|             } |             } | ||||||
|         } |             finally | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public virtual ITcpDmtpClient Connect(CancellationToken token, int timeout = 5000) |  | ||||||
|         { |  | ||||||
|             lock (this.SyncRoot) |  | ||||||
|             { |             { | ||||||
|                 if (this.IsHandshaked) |                 this.m_semaphoreForConnect.Release(); | ||||||
|                 { |  | ||||||
|                     return this; |  | ||||||
|                 } |  | ||||||
|                 if (!this.Online) |  | ||||||
|                 { |  | ||||||
|                     base.Connect(timeout); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 this.m_smtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |  | ||||||
|                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); |  | ||||||
|                 return this; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 建立Tcp连接,并且执行握手。 |         /// 异步进行Dmtp协议的握手连接 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="timeout"></param> |         /// <param name="timeout"></param> | ||||||
|  |         /// <param name="token"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public override async Task<ITcpClient> ConnectAsync(int timeout = 5000) |         public override async Task ConnectAsync(int timeout, CancellationToken token) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 await this.m_semaphore.WaitAsync(); |                 await this.m_semaphoreForConnect.WaitAsync(timeout, token); | ||||||
|                 if (this.IsHandshaked) |                 if (this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
|                     return this; |                     return; | ||||||
|                 } |  | ||||||
|                 if (!this.Online) |  | ||||||
|                 { |  | ||||||
|                     await base.ConnectAsync(timeout); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |  | ||||||
|                      this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), CancellationToken.None); |  | ||||||
|                 return this; |  | ||||||
|             } |  | ||||||
|             finally |  | ||||||
|             { |  | ||||||
|                 this.m_semaphore.Release(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public virtual async Task<ITcpDmtpClient> ConnectAsync(CancellationToken token, int timeout = 5000) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 await this.m_semaphore.WaitAsync(); |  | ||||||
|                 if (this.IsHandshaked) |  | ||||||
|                 { |  | ||||||
|                     return this; |  | ||||||
|                 } |                 } | ||||||
|                 if (!this.Online) |                 if (!this.Online) | ||||||
|                 { |                 { | ||||||
|                     await base.ConnectAsync(timeout, token); |                     await base.ConnectAsync(timeout, token); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |                 await this.m_dmtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken, | ||||||
|                      this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); |                      this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Id, timeout, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Metadata, token); | ||||||
|                 return this; |  | ||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|                 this.m_semaphore.Release(); |                 this.m_semaphoreForConnect.Release(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -174,13 +159,13 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> |         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||||
|         public void ResetId(string id) |         public void ResetId(string id) | ||||||
|         { |         { | ||||||
|             this.m_smtpActor.ResetId(id); |             this.m_dmtpActor.ResetId(id); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> |         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||||
|         public Task ResetIdAsync(string newId) |         public Task ResetIdAsync(string newId) | ||||||
|         { |         { | ||||||
|             return this.m_smtpActor.ResetIdAsync(newId); |             return this.m_dmtpActor.ResetIdAsync(newId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion ResetId |         #endregion ResetId | ||||||
| @@ -229,13 +214,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|         #endregion 发送 |         #endregion 发送 | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override void Dispose(bool disposing) |  | ||||||
|         { |  | ||||||
|             this.DmtpActor.SafeDispose(); |  | ||||||
|             base.Dispose(disposing); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override void LoadConfig(TouchSocketConfig config) |         protected override void LoadConfig(TouchSocketConfig config) | ||||||
|         { |         { | ||||||
| @@ -246,37 +224,31 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 this.m_allowRoute = true; |                 this.m_allowRoute = true; | ||||||
|                 this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor; |                 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, |                 OutputSend = this.DmtpActorSend, | ||||||
|                 OnRouting = this.OnDmtpActorRouting, |                 OutputSendAsync = this.DmtpActorSendAsync, | ||||||
|                 OnHandshaking = this.OnDmtpActorHandshaking, |                 Routing = this.OnDmtpActorRouting, | ||||||
|                 OnHandshaked = this.OnDmtpActorHandshaked, |                 Handshaking = this.OnDmtpActorHandshaking, | ||||||
|                 OnClose = this.OnDmtpActorClose, |                 Handshaked = this.OnDmtpActorHandshaked, | ||||||
|  |                 Closed = this.OnDmtpActorClose, | ||||||
|                 Logger = this.Logger, |                 Logger = this.Logger, | ||||||
|                 Client = this, |                 Client = this, | ||||||
|                 OnFindDmtpActor = this.m_findDmtpActor, |                 FindDmtpActor = this.m_findDmtpActor, | ||||||
|                 OnCreateChannel = this.OnDmtpActorCreateChannel |                 CreatedChannel = this.OnDmtpActorCreateChannel | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override async Task OnDisconnected(DisconnectEventArgs e) |  | ||||||
|         { |  | ||||||
|             await base.OnDisconnected(e); |  | ||||||
|             this.DmtpActor.Close(false, e.Message); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) |         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||||
|         { |         { | ||||||
|             var message = (DmtpMessage)e.RequestInfo; |             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 内部委托绑定 |         #region 内部委托绑定 | ||||||
| @@ -286,52 +258,35 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             base.Send(transferBytes); |             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); |             this.BreakOut(false, msg); | ||||||
|             if (e.Handled) |             return EasyTask.CompletedTask; | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaked(e); |             return this.OnCreatedChannel(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaking(e); |             return this.OnHandshaked(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, 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.OnHandshaking(e); | ||||||
|             { |         } | ||||||
|                 return; |  | ||||||
|             } |         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||||
|             this.OnRouting(e); |         { | ||||||
|  |             return this.OnRouting(e); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion 内部委托绑定 |         #endregion 内部委托绑定 | ||||||
| @@ -342,32 +297,53 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 当创建通道 |         /// 当创建通道 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在完成握手连接时 |         /// 在完成握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 即将握手连接时 |         /// 即将握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e">参数</param> |         /// <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> | ||||||
|         /// 当需要转发路由包时 |         /// 当需要转发路由包时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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 事件触发 |         #endregion 事件触发 | ||||||
|   | |||||||
| @@ -41,14 +41,14 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         #region 字段 |         #region 字段 | ||||||
|  |  | ||||||
|         private bool m_allowRoute; |         private bool m_allowRoute; | ||||||
|         private Func<string, IDmtpActor> m_findDmtpActor; |         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||||
|  |  | ||||||
|         #endregion 字段 |         #endregion 字段 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 连接令箭 |         /// 连接令箭 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public string VerifyToken => this.Config?.GetValue(DmtpConfigExtension.VerifyTokenProperty); |         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override void LoadConfig(TouchSocketConfig config) |         protected override void LoadConfig(TouchSocketConfig config) | ||||||
| @@ -73,14 +73,25 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute) |             socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute) | ||||||
|             { |             { | ||||||
|                 Id = e.Id, |                 Id = e.Id, | ||||||
|                 OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null |                 FindDmtpActor = this.FindDmtpActor | ||||||
|             }); |             }); | ||||||
|             await base.OnConnecting(socketClient, e); |             await base.OnConnecting(socketClient, e); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private IDmtpActor OnServiceFindDmtpActor(string id) |         private async Task<IDmtpActor> FindDmtpActor(string id) | ||||||
|         { |         { | ||||||
|             return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; |             if (this.m_allowRoute) | ||||||
|  |             { | ||||||
|  |                 if (this.m_findDmtpActor != null) | ||||||
|  |                 { | ||||||
|  |                     return await this.m_findDmtpActor.Invoke(id); | ||||||
|  |                 } | ||||||
|  |                 return this.TryGetSocketClient(id, out var client) ? client.DmtpActor : null; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -30,7 +30,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public partial class TcpDmtpSocketClient : SocketClient, ITcpDmtpSocketClient |     public partial class TcpDmtpSocketClient : SocketClient, ITcpDmtpSocketClient | ||||||
|     { |     { | ||||||
|         private DmtpActor m_smtpActor; |         private DmtpActor m_dmtpActor; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// TcpDmtpSocketClient |         /// TcpDmtpSocketClient | ||||||
| @@ -41,53 +41,40 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public IDmtpActor DmtpActor { get => this.m_smtpActor; } |         public IDmtpActor DmtpActor { get => this.m_dmtpActor; } | ||||||
|  |  | ||||||
|         /// <inheritdoc cref="IDmtpActor.IsHandshaked"/> |         /// <inheritdoc cref="IHandshakeObject.IsHandshaked"/> | ||||||
|         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; |         public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 验证超时时间,默认为3000ms |         /// 验证超时时间,默认为3000ms | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public int VerifyTimeout => this.Config.GetValue(DmtpConfigExtension.VerifyTimeoutProperty); |         public TimeSpan VerifyTimeout => this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyTimeout; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 连接令箭 |         /// 连接令箭 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty); |         public string VerifyToken => this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken; | ||||||
|  |  | ||||||
|         #region 内部委托绑定 |         #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); |             return this.OnCreateChannel(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaked(e); |             return this.OnHandshaked(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) |         private async Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             if (e.Token == this.VerifyToken) |             if (e.Token == this.VerifyToken) | ||||||
|             { |             { | ||||||
| @@ -98,25 +85,12 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                 e.Message = "Token不受理"; |                 e.Message = "Token不受理"; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             this.OnHandshaking(e); |             await this.OnHandshaking(e).ConfigureFalseAwait(); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) |         private Task OnDmtpActorRouting(DmtpActor actor, PackageRouterEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnRouting(e); |             return this.OnRouting(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(IDmtpRoutingPlugin.OnDmtpRouting), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion 内部委托绑定 |         #endregion 内部委托绑定 | ||||||
| @@ -127,99 +101,147 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 当创建通道 |         /// 当创建通道 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在完成握手连接时 |         /// 在完成握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在验证Token时 |         /// 在验证Token时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e">参数</param> |         /// <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> | ||||||
|         /// 在需要转发路由包时。 |         /// 在需要转发路由包时。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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 事件 |         #endregion 事件 | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         #region 断开 | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="msg"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|         public override void Close(string msg = "") |         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 |         #region ResetId | ||||||
|  |  | ||||||
|         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> |         ///<inheritdoc cref="IDmtpActor.ResetId(string)"/> | ||||||
|         public override void ResetId(string id) |         public override void ResetId(string id) | ||||||
|         { |         { | ||||||
|             this.m_smtpActor.ResetId(id); |             this.m_dmtpActor.ResetId(id); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> |         ///<inheritdoc cref="IDmtpActor.ResetIdAsync(string)"/> | ||||||
|         public Task ResetIdAsync(string newId) |         public Task ResetIdAsync(string newId) | ||||||
|         { |         { | ||||||
|             return this.m_smtpActor.ResetIdAsync(newId); |             return this.m_dmtpActor.ResetIdAsync(newId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion ResetId |         #endregion ResetId | ||||||
|  |  | ||||||
|         internal void SetDmtpActor(DmtpActor actor) |         internal void SetDmtpActor(DmtpActor actor) | ||||||
|         { |         { | ||||||
|             actor.OnResetId = this.ThisOnResetId; |             actor.IdChanged = this.ThisOnResetId; | ||||||
|             actor.OutputSend = this.ThisDmtpActorOutputSend; |             actor.OutputSend = this.ThisDmtpActorOutputSend; | ||||||
|  |             actor.OutputSendAsync = this.ThisDmtpActorOutputSendAsync; | ||||||
|             actor.Client = this; |             actor.Client = this; | ||||||
|             actor.OnClose = this.OnDmtpActorClose; |             actor.Closed = this.OnDmtpActorClose; | ||||||
|             actor.OnRouting = this.OnDmtpActorRouting; |             actor.Routing = this.OnDmtpActorRouting; | ||||||
|             actor.OnHandshaked = this.OnDmtpActorHandshaked; |             actor.Handshaked = this.OnDmtpActorHandshaked; | ||||||
|             actor.OnHandshaking = this.OnDmtpActorHandshaking; |             actor.Handshaking = this.OnDmtpActorHandshaking; | ||||||
|             actor.OnCreateChannel = this.OnDmtpActorCreateChannel; |             actor.CreatedChannel = this.OnDmtpActorCreateChannel; | ||||||
|             actor.Logger = this.Logger; |             actor.Logger = this.Logger; | ||||||
|             this.m_smtpActor = actor; |             this.m_dmtpActor = actor; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override void Dispose(bool disposing) |  | ||||||
|         { |  | ||||||
|             this.DmtpActor.SafeDispose(); |  | ||||||
|             base.Dispose(disposing); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override async Task ReceivedData(ReceivedDataEventArgs e) |         protected override async Task ReceivedData(ReceivedDataEventArgs e) | ||||||
|         { |         { | ||||||
|             var message = (DmtpMessage)e.RequestInfo; |             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/> |         /// <inheritdoc/> | ||||||
|         protected override async Task OnConnected(ConnectedEventArgs e) |         protected override async Task OnConnected(ConnectedEventArgs e) | ||||||
|         { |         { | ||||||
|             this.m_smtpActor.Id = this.Id; |             this.m_dmtpActor.Id = this.Id; | ||||||
|             await base.OnConnected(e); |             await base.OnConnected(e).ConfigureFalseAwait(); | ||||||
|  |  | ||||||
|             _ = Task.Run(async () => |             _ = Task.Run(async () => | ||||||
|             { |             { | ||||||
|                 await Task.Delay(this.VerifyTimeout); |                 await Task.Delay(this.VerifyTimeout).ConfigureFalseAwait(); | ||||||
|                 if (!this.IsHandshaked) |                 if (!this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
|                     this.TryShutdown(); |                     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) |         private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||||
|         { |         { | ||||||
|             base.Send(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 发送 |         #region 发送 | ||||||
|   | |||||||
| @@ -84,7 +84,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             var message = DmtpMessage.CreateFrom(e.ByteBlock); |             var message = DmtpMessage.CreateFrom(e.ByteBlock); | ||||||
|             if (!client.InputReceivedData(message)) |             if (!await client.InputReceivedData(message)) | ||||||
|             { |             { | ||||||
|                 if (this.PluginsManager.Enable) |                 if (this.PluginsManager.Enable) | ||||||
|                 { |                 { | ||||||
|   | |||||||
| @@ -45,16 +45,17 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         { |         { | ||||||
|             this.Id = endPoint.ToString(); |             this.Id = endPoint.ToString(); | ||||||
|             this.OutputSend = this.RpcActorSend; |             this.OutputSend = this.RpcActorSend; | ||||||
|             this.OnCreateChannel = this.OnDmtpActorCreateChannel; |             this.OutputSendAsync = this.RpcActorSendAsync; | ||||||
|  |             this.CreatedChannel = this.OnDmtpActorCreatedChannel; | ||||||
|             this.m_udpSession = udpSession; |             this.m_udpSession = udpSession; | ||||||
|             this.m_endPoint = endPoint; |             this.m_endPoint = endPoint; | ||||||
|             this.Logger = logger; |             this.Logger = logger; | ||||||
|             this.Client = this; |             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) |         public bool Created(IPluginsManager pluginsManager) | ||||||
| @@ -117,5 +118,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         { |         { | ||||||
|             this.m_udpSession.Send(this.m_endPoint, transferBytes); |             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); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// IWebSocketDmtpClient |     /// IWebSocketDmtpClient | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public interface IWebSocketDmtpClient : IWebSocketDmtpClientBase |     public interface IWebSocketDmtpClient : IWebSocketDmtpClientBase, ISetupConfigObject | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 异步连接 |         /// 异步连接 | ||||||
|   | |||||||
| @@ -22,14 +22,5 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         string Id { get; } |         string Id { get; } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 加载到当前客户端的配置 |  | ||||||
|         /// </summary> |  | ||||||
|         TouchSocketConfig Config { get; } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 是否已完成<see cref="IDmtpActor.IsHandshaked"/> |  | ||||||
|         /// </summary> |  | ||||||
|         bool IsHandshaked { get; } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -29,7 +29,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// WebSocketDmtpClient |     /// WebSocketDmtpClient | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class WebSocketDmtpClient : BaseSocket, IWebSocketDmtpClient |     public class WebSocketDmtpClient : SetupConfigObject, IWebSocketDmtpClient | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// WebSocketDmtpClient |         /// WebSocketDmtpClient | ||||||
| @@ -50,28 +50,23 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|         #region 字段 |         #region 字段 | ||||||
|  |  | ||||||
|         private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); |         private readonly SemaphoreSlim m_semaphoreForConnect = new SemaphoreSlim(1, 1); | ||||||
|  |         private readonly SemaphoreSlim m_semaphoreForSend = new SemaphoreSlim(1, 1); | ||||||
|         private ClientWebSocket m_client; |         private ClientWebSocket m_client; | ||||||
|         private SealedDmtpActor m_dmtpActor; |         private SealedDmtpActor m_dmtpActor; | ||||||
|         private Func<string, IDmtpActor> m_findDmtpActor; |         private Func<string, Task<IDmtpActor>> m_findDmtpActor; | ||||||
|         private int m_receiveBufferSize = 1024 * 10; |         private int m_receiveBufferSize = 1024 * 10; | ||||||
|         private ValueCounter m_receiveCounter; |         private ValueCounter m_receiveCounter; | ||||||
|         private int m_sendBufferSize = 1024 * 10; |         private int m_sendBufferSize = 1024 * 10; | ||||||
|         private ValueCounter m_sendCounter; |         private ValueCounter m_sendCounter; | ||||||
|         private TcpDmtpAdapter m_smtpAdapter; |         private TcpDmtpAdapter m_dmtpAdapter; | ||||||
|  |  | ||||||
|         #endregion 字段 |         #endregion 字段 | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public bool CanSend => this.m_client.State == WebSocketState.Open; |         public bool CanSend => this.m_client.State == WebSocketState.Open; | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 客户端配置 |  | ||||||
|         /// </summary> |  | ||||||
|         public TouchSocketConfig Config { get; private set; } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public IContainer Container { get; private set; } |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 断开连接 |         /// 断开连接 | ||||||
| @@ -93,20 +88,14 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public DateTime LastSendTime => this.m_sendCounter.LastIncrement; |         public DateTime LastSendTime => this.m_sendCounter.LastIncrement; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public IPluginsManager PluginsManager { get; private set; } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public Protocol Protocol { get; set; } = DmtpUtility.DmtpProtocol; |         public Protocol Protocol { get; set; } = DmtpUtility.DmtpProtocol; | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override int ReceiveBufferSize => this.m_receiveBufferSize; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public IPHost RemoteIPHost { get; private set; } |         public IPHost RemoteIPHost { get; private set; } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override int SendBufferSize => this.m_sendBufferSize; |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 发送<see cref="IDmtpActor"/>关闭消息。 |         /// 发送<see cref="IDmtpActor"/>关闭消息。 | ||||||
| @@ -115,56 +104,15 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public void Close(string msg = "") |         public void Close(string msg = "") | ||||||
|         { |         { | ||||||
|             this.DmtpActor.Close(true, msg); |             this.m_dmtpActor.SendClose(msg); | ||||||
|  |             this.m_dmtpActor.Close(msg); | ||||||
|             this.PrivateClose(msg); |             this.PrivateClose(msg); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public async Task ConnectAsync(int timeout = 5000) |         public Task ConnectAsync(int timeout = 5000) | ||||||
|         { |         { | ||||||
|             try |             return this.ConnectAsync(CancellationToken.None, timeout); | ||||||
|             { |  | ||||||
|                 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(); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
| @@ -172,7 +120,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 await this.m_semaphore.WaitAsync(); |                 await this.m_semaphoreForConnect.WaitAsync(); | ||||||
|                 if (this.IsHandshaked) |                 if (this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
|                     return; |                     return; | ||||||
| @@ -187,31 +135,32 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                     this.m_dmtpActor = new SealedDmtpActor(false) |                     this.m_dmtpActor = new SealedDmtpActor(false) | ||||||
|                     { |                     { | ||||||
|                         OutputSend = this.OnDmtpActorSend, |                         OutputSend = this.OnDmtpActorSend, | ||||||
|                         OnRouting = this.OnDmtpActorRouting, |                         OutputSendAsync = this.OnDmtpActorSendAsync, | ||||||
|                         OnHandshaking = this.OnDmtpActorHandshaking, |                         Routing = this.OnDmtpActorRouting, | ||||||
|                         OnHandshaked = this.OnDmtpActorHandshaked, |                         Handshaking = this.OnDmtpActorHandshaking, | ||||||
|                         OnClose = this.OnDmtpActorClose, |                         Handshaked = this.OnDmtpActorHandshaked, | ||||||
|  |                         Closed = this.OnDmtpActorClose, | ||||||
|                         Logger = this.Logger, |                         Logger = this.Logger, | ||||||
|                         Client = this, |                         Client = this, | ||||||
|                         OnFindDmtpActor = this.m_findDmtpActor, |                         FindDmtpActor = this.m_findDmtpActor, | ||||||
|                         OnCreateChannel = this.OnDmtpActorCreateChannel |                         CreatedChannel = this.OnDmtpActorCreateChannel | ||||||
|                     }; |                     }; ; | ||||||
|  |  | ||||||
|                     this.m_smtpAdapter = new TcpDmtpAdapter() |                     this.m_dmtpAdapter = new TcpDmtpAdapter() | ||||||
|                     { |                     { | ||||||
|                         ReceivedCallBack = this.PrivateHandleReceivedData |                         ReceivedCallBack = this.PrivateHandleReceivedData | ||||||
|                     }; |                     }; | ||||||
|                     _ = this.BeginReceive(); |                     _ = this.BeginReceive(); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), |                 this.m_dmtpActor.Handshake(this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).VerifyToken, | ||||||
|                     this.Config.GetValue(DmtpConfigExtension.DefaultIdProperty), |                    this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Id, | ||||||
|                     timeout, this.Config.GetValue(DmtpConfigExtension.MetadataProperty), token); |                    timeout, this.Config.GetValue(DmtpConfigExtension.DmtpOptionProperty).Metadata, token); | ||||||
|                 this.IsHandshaked = true; |                 this.IsHandshaked = true; | ||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|                 this.m_semaphore.Release(); |                 this.m_semaphoreForConnect.Release(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -233,28 +182,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             this.DmtpActor.ResetId(newId); |             this.DmtpActor.ResetId(newId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 配置 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <exception cref="Exception"></exception> |  | ||||||
|         public IWebSocketDmtpClient Setup(TouchSocketConfig config) |  | ||||||
|         { |  | ||||||
|             if (config == null) |  | ||||||
|             { |  | ||||||
|                 throw new ArgumentNullException(nameof(config)); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             this.ThrowIfDisposed(); |  | ||||||
|  |  | ||||||
|             this.BuildConfig(config); |  | ||||||
|  |  | ||||||
|             this.PluginsManager.Raise(nameof(ILoadingConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config)); |  | ||||||
|             this.LoadConfig(this.Config); |  | ||||||
|             this.PluginsManager.Raise(nameof(ILoadedConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config)); |  | ||||||
|  |  | ||||||
|             return this; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override void Dispose(bool disposing) |         protected override void Dispose(bool disposing) | ||||||
| @@ -275,11 +202,9 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 加载配置 |         /// 加载配置 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="config"></param> |         /// <param name="config"></param> | ||||||
|         protected virtual void LoadConfig(TouchSocketConfig config) |         protected override void LoadConfig(TouchSocketConfig config) | ||||||
|         { |         { | ||||||
|             this.RemoteIPHost = config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty); |             this.RemoteIPHost = config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty); | ||||||
|             this.Logger ??= this.Container.Resolve<ILog>(); |  | ||||||
|  |  | ||||||
|             if (this.Container.IsRegistered(typeof(IDmtpRouteService))) |             if (this.Container.IsRegistered(typeof(IDmtpRouteService))) | ||||||
|             { |             { | ||||||
|                 this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor; |                 this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor; | ||||||
| @@ -305,7 +230,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|             { |             { | ||||||
|                 while (true) |                 while (true) | ||||||
|                 { |                 { | ||||||
|                     using (var byteBlock = new ByteBlock(this.ReceiveBufferSize)) |                     using (var byteBlock = new ByteBlock(this.m_receiveBufferSize)) | ||||||
|                     { |                     { | ||||||
|                         var result = await this.m_client.ReceiveAsync(new ArraySegment<byte>(byteBlock.Buffer, 0, byteBlock.Capacity), default); |                         var result = await this.m_client.ReceiveAsync(new ArraySegment<byte>(byteBlock.Buffer, 0, byteBlock.Capacity), default); | ||||||
|                         if (result.Count == 0) |                         if (result.Count == 0) | ||||||
| @@ -315,7 +240,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                         byteBlock.SetLength(result.Count); |                         byteBlock.SetLength(result.Count); | ||||||
|                         this.m_receiveCounter.Increment(result.Count); |                         this.m_receiveCounter.Increment(result.Count); | ||||||
|  |  | ||||||
|                         this.m_smtpAdapter.ReceivedInput(byteBlock); |                         this.m_dmtpAdapter.ReceivedInput(byteBlock); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -329,7 +254,7 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|         private void BreakOut(string msg, bool manual) |         private void BreakOut(string msg, bool manual) | ||||||
|         { |         { | ||||||
|             lock (this.SyncRoot) |             lock (this.m_semaphoreForConnect) | ||||||
|             { |             { | ||||||
|                 if (this.IsHandshaked) |                 if (this.IsHandshaked) | ||||||
|                 { |                 { | ||||||
| @@ -337,53 +262,12 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|                     this.m_client.CloseAsync(WebSocketCloseStatus.NormalClosure, msg, CancellationToken.None); |                     this.m_client.CloseAsync(WebSocketCloseStatus.NormalClosure, msg, CancellationToken.None); | ||||||
|                     this.m_client.SafeDispose(); |                     this.m_client.SafeDispose(); | ||||||
|                     this.DmtpActor.SafeDispose(); |                     this.DmtpActor.SafeDispose(); | ||||||
|                     this.m_smtpAdapter.SafeDispose(); |                     this.m_dmtpAdapter.SafeDispose(); | ||||||
|                     this.OnDisconnected(new DisconnectEventArgs(manual, msg)); |                     this.OnDisconnected(new DisconnectEventArgs(manual, msg)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void BuildConfig(TouchSocketConfig config) |  | ||||||
|         { |  | ||||||
|             this.Config = config; |  | ||||||
|  |  | ||||||
|             if (!(config.GetValue(TouchSocketCoreConfigExtension.ContainerProperty) is IContainer container)) |  | ||||||
|             { |  | ||||||
|                 container = new Container(); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (!container.IsRegistered(typeof(ILog))) |  | ||||||
|             { |  | ||||||
|                 container.RegisterSingleton<ILog, LoggerGroup>(); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (!(config.GetValue(TouchSocketCoreConfigExtension.PluginsManagerProperty) is IPluginsManager pluginsManager)) |  | ||||||
|             { |  | ||||||
|                 pluginsManager = new PluginsManager(container); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (container.IsRegistered(typeof(IPluginsManager))) |  | ||||||
|             { |  | ||||||
|                 pluginsManager = container.Resolve<IPluginsManager>(); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 container.RegisterSingleton<IPluginsManager>(pluginsManager); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (config.GetValue(TouchSocketCoreConfigExtension.ConfigureContainerProperty) is Action<IContainer> actionContainer) |  | ||||||
|             { |  | ||||||
|                 actionContainer.Invoke(container); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (config.GetValue(TouchSocketCoreConfigExtension.ConfigurePluginsProperty) is Action<IPluginsManager> actionPluginsManager) |  | ||||||
|             { |  | ||||||
|                 pluginsManager.Enable = true; |  | ||||||
|                 actionPluginsManager.Invoke(pluginsManager); |  | ||||||
|             } |  | ||||||
|             this.Container = container; |  | ||||||
|             this.PluginsManager = pluginsManager; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private void OnReceivePeriod(long value) |         private void OnReceivePeriod(long value) | ||||||
|         { |         { | ||||||
| @@ -403,78 +287,89 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) |         private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) | ||||||
|         { |         { | ||||||
|             var message = (DmtpMessage)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)); |                 this.PluginsManager?.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region 内部委托绑定 |         #region 内部委托绑定 | ||||||
|  |  | ||||||
|         private void OnDmtpActorClose(DmtpActor actor, string arg2) |         private Task OnDmtpActorClose(DmtpActor actor, string arg2) | ||||||
|         { |         { | ||||||
|             this.PrivateClose(arg2); |             this.PrivateClose(arg2); | ||||||
|  |             return EasyTask.CompletedTask; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) |         private Task OnDmtpActorCreateChannel(DmtpActor actor, CreateChannelEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnCreateChannel(e); |             return this.OnCreateChannel(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpCreateChannelPlugin.OnCreateChannel), this, e); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaked(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaked(e); |             return this.OnHandshaked(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             if (this.PluginsManager.Raise(nameof(IDmtpHandshakedPlugin.OnDmtpHandshaked), this, e)) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) |         private Task OnDmtpActorHandshaking(DmtpActor actor, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             this.OnHandshaking(e); |             return this.OnHandshaking(e); | ||||||
|             if (e.Handled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             this.PluginsManager.Raise(nameof(IDmtpHandshakingPlugin.OnDmtpHandshaking), this, 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) |         private void OnDmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) | ||||||
|         { |         { | ||||||
|             for (var i = 0; i < transferBytes.Length; i++) |             try | ||||||
|             { |             { | ||||||
|                 Task task; |                 this.m_semaphoreForSend.Wait(); | ||||||
|                 if (i == transferBytes.Length - 1) |                 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.GetFalseAwaitResult(); |  | ||||||
|                 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 内部委托绑定 |         #endregion 内部委托绑定 | ||||||
| @@ -485,32 +380,53 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// 当创建通道 |         /// 当创建通道 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 在完成握手连接时 |         /// 在完成握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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> | ||||||
|         /// 即将握手连接时 |         /// 即将握手连接时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e">参数</param> |         /// <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> | ||||||
|         /// 当需要转发路由包时 |         /// 当需要转发路由包时 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="e"></param> |         /// <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 事件触发 |         #endregion 事件触发 | ||||||
|   | |||||||
| @@ -18,77 +18,20 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     public static class DmtpConfigExtension |     public static class DmtpConfigExtension | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 默认使用Id。 |         /// 设置Dmtp相关配置。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static readonly DependencyProperty<string> DefaultIdProperty = |         public static readonly DependencyProperty<DmtpOption> DmtpOptionProperty = | ||||||
|             DependencyProperty<string>.Register("DefaultId", null); |             DependencyProperty<DmtpOption>.Register("DmtpOption", new DmtpOption()); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// DmtpClient连接时的元数据, 所需类型<see cref="Metadata"/> |         /// 设置Dmtp相关配置。 | ||||||
|         /// </summary> |  | ||||||
|         public static readonly DependencyProperty<Metadata> MetadataProperty = DependencyProperty<Metadata>.Register("Metadata", null); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 验证超时时间,默认为3000ms, 所需类型<see cref="int"/> |  | ||||||
|         /// </summary> |  | ||||||
|         public static readonly DependencyProperty<int> VerifyTimeoutProperty = |  | ||||||
|             DependencyProperty<int>.Register("VerifyTimeout", 3000); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 连接令箭,当为null或空时,重置为默认值“rrqm”, 所需类型<see cref="string"/> |  | ||||||
|         /// </summary> |  | ||||||
|         public static readonly DependencyProperty<string> VerifyTokenProperty = |  | ||||||
|             DependencyProperty<string>.Register("VerifyToken", "rrqm"); |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 设置默认的使用Id。仅在DmtpRpc组件适用。 |  | ||||||
|         /// <para> |  | ||||||
|         /// 使用该功能时,仅在服务器的Handshaking之后生效。且如果id重复,则会连接失败。 |  | ||||||
|         /// </para> |  | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="config"></param> |         /// <param name="config"></param> | ||||||
|         /// <param name="value"></param> |         /// <param name="value"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static TouchSocketConfig SetDefaultId(this TouchSocketConfig config, string value) |         public static TouchSocketConfig SetDmtpOption(this TouchSocketConfig config, DmtpOption value) | ||||||
|         { |         { | ||||||
|             config.SetValue(DefaultIdProperty, value); |             config.SetValue(DmtpOptionProperty, value); | ||||||
|             return config; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 设置DmtpClient连接时的元数据 |  | ||||||
|         /// <para>仅适用于DmtpClient系类</para> |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <param name="value"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public static TouchSocketConfig SetMetadata(this TouchSocketConfig config, Metadata value) |  | ||||||
|         { |  | ||||||
|             config.SetValue(MetadataProperty, value); |  | ||||||
|             return config; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 验证超时时间,默认为3000ms. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <param name="value"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public static TouchSocketConfig SetVerifyTimeout(this TouchSocketConfig config, int value) |  | ||||||
|         { |  | ||||||
|             config.SetValue(VerifyTimeoutProperty, value); |  | ||||||
|             return config; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 连接令箭,当为null或空时,重置为默认值“rrqm” |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="config"></param> |  | ||||||
|         /// <param name="value"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public static TouchSocketConfig SetVerifyToken(this TouchSocketConfig config, string value) |  | ||||||
|         { |  | ||||||
|             config.SetValue(VerifyTokenProperty, value); |  | ||||||
|             return config; |             return config; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -183,32 +126,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|  |  | ||||||
|         #endregion 创建HttpDmtp |         #endregion 创建HttpDmtp | ||||||
|  |  | ||||||
|         //#region 创建UdpTouchRpc |  | ||||||
|  |  | ||||||
|         ///// <summary> |  | ||||||
|         ///// 构建UdpTouchRpc类 |  | ||||||
|         ///// </summary> |  | ||||||
|         ///// <typeparam name="TClient"></typeparam> |  | ||||||
|         ///// <param name="config"></param> |  | ||||||
|         ///// <returns></returns> |  | ||||||
|         //public static TClient BuildWithUdpTouchRpc<TClient>(this TouchSocketConfig config) where TClient : IUdpTouchRpc |  | ||||||
|         //{ |  | ||||||
|         //    TClient client = Activator.CreateInstance<TClient>(); |  | ||||||
|         //    client.Setup(config); |  | ||||||
|         //    client.Start(); |  | ||||||
|         //    return client; |  | ||||||
|         //} |  | ||||||
|  |  | ||||||
|         ///// <summary> |  | ||||||
|         ///// 构建UdpTouchRpc类客户端 |  | ||||||
|         ///// </summary> |  | ||||||
|         ///// <param name="config"></param> |  | ||||||
|         ///// <returns></returns> |  | ||||||
|         //public static UdpTouchRpc BuildWithUdpTouchRpc(this TouchSocketConfig config) |  | ||||||
|         //{ |  | ||||||
|         //    return BuildWithUdpTouchRpc<UdpTouchRpc>(config); |  | ||||||
|         //} |  | ||||||
|  |  | ||||||
|         //#endregion 创建UdpTouchRpc |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -22,10 +22,10 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 创建一个<see cref="DmtpFileTransferActor"/> |         /// 创建一个<see cref="DmtpFileTransferActor"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         public DmtpFileTransferActor(IDmtpActor smtpActor) |         public DmtpFileTransferActor(IDmtpActor dmtpActor) | ||||||
|         { |         { | ||||||
|             this.DmtpActor = smtpActor; |             this.DmtpActor = dmtpActor; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region 委托 |         #region 委托 | ||||||
| @@ -61,12 +61,8 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|  |  | ||||||
|         #endregion 字段 |         #endregion 字段 | ||||||
|  |  | ||||||
|         /// <summary> |         /// <inheritdoc/> | ||||||
|         /// 处理收到的消息 |         public async Task<bool> InputReceivedData(DmtpMessage message) | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="message"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public bool InputReceivedData(DmtpMessage message) |  | ||||||
|         { |         { | ||||||
|             var byteBlock = message.BodyByteBlock; |             var byteBlock = message.BodyByteBlock; | ||||||
|             if (message.ProtocolFlags == this.m_pullFileResourceInfo_Request) |             if (message.ProtocolFlags == this.m_pullFileResourceInfo_Request) | ||||||
| @@ -77,9 +73,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileResource.UnpackageRouter(byteBlock); |                     waitFileResource.UnpackageRouter(byteBlock); | ||||||
|                     if (waitFileResource.Route && this.DmtpActor.AllowRoute) |                     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); |                                 actor.Send(this.m_pullFileResourceInfo_Request, byteBlock); | ||||||
|                                 return true; |                                 return true; | ||||||
| @@ -101,7 +97,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         waitFileResource.UnpackageBody(byteBlock); |                         waitFileResource.UnpackageBody(byteBlock); | ||||||
|                         Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource); |                         _ = Task.Factory.StartNew(this.RequestPullFileResourceInfo, waitFileResource); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
| @@ -118,7 +114,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileResource.UnpackageRouter(byteBlock); |                     waitFileResource.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFileResource.Route) |                     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); |                             actor.Send(this.m_pullFileResourceInfo_Response, byteBlock); | ||||||
|                         } |                         } | ||||||
| @@ -143,9 +139,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileSection.UnpackageRouter(byteBlock); |                     waitFileSection.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) |                     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 |                         else | ||||||
|                         { |                         { | ||||||
| @@ -153,7 +149,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                             waitFileSection.SwitchId(); |                             waitFileSection.SwitchId(); | ||||||
|                             byteBlock.Reset(); |                             byteBlock.Reset(); | ||||||
|                             waitFileSection.Package(byteBlock); |                             waitFileSection.Package(byteBlock); | ||||||
|                             this.DmtpActor.Send(this.m_pullFileSection_Response, byteBlock); |                             await this.DmtpActor.SendAsync(this.m_pullFileSection_Response, byteBlock); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
| @@ -177,9 +173,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileSection.UnpackageRouter(byteBlock); |                     waitFileSection.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) |                     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 |                     else | ||||||
| @@ -202,11 +198,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileResource.UnpackageRouter(byteBlock); |                     waitFileResource.UnpackageRouter(byteBlock); | ||||||
|                     if (waitFileResource.Route && this.DmtpActor.AllowRoute) |                     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; |                                 return true; | ||||||
|                             } |                             } | ||||||
|                             else |                             else | ||||||
| @@ -221,12 +217,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                         byteBlock.Reset(); |                         byteBlock.Reset(); | ||||||
|                         waitFileResource.SwitchId(); |                         waitFileResource.SwitchId(); | ||||||
|                         waitFileResource.Package(byteBlock); |                         waitFileResource.Package(byteBlock); | ||||||
|                         this.DmtpActor.Send(this.m_pushFileResourceInfo_Response, byteBlock); |                         await this.DmtpActor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock); | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         waitFileResource.UnpackageBody(byteBlock); |                         waitFileResource.UnpackageBody(byteBlock); | ||||||
|                         Task.Factory.StartNew(this.RequestPushFileResourceInfo, waitFileResource); |                         _ = this.RequestPushFileResourceInfo(waitFileResource); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
| @@ -243,9 +239,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileResource.UnpackageRouter(byteBlock); |                     waitFileResource.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFileResource.Route) |                     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 |                     else | ||||||
| @@ -268,9 +264,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileSection.UnpackageRouter(byteBlock); |                     waitFileSection.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) |                     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 |                         else | ||||||
|                         { |                         { | ||||||
| @@ -278,7 +274,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                             waitFileSection.SwitchId(); |                             waitFileSection.SwitchId(); | ||||||
|                             byteBlock.Reset(); |                             byteBlock.Reset(); | ||||||
|                             waitFileSection.Package(byteBlock); |                             waitFileSection.Package(byteBlock); | ||||||
|                             this.DmtpActor.Send(this.m_pushFileSection_Response, byteBlock); |                             await this.DmtpActor.SendAsync(this.m_pushFileSection_Response, byteBlock); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
| @@ -303,9 +299,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFileSection.UnpackageRouter(byteBlock); |                     waitFileSection.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFileSection.Route) |                     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 |                     else | ||||||
| @@ -328,9 +324,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFinishedPackage.UnpackageRouter(byteBlock); |                     waitFinishedPackage.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFinishedPackage.Route) |                     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 |                         else | ||||||
|                         { |                         { | ||||||
| @@ -338,13 +334,13 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                             waitFinishedPackage.SwitchId(); |                             waitFinishedPackage.SwitchId(); | ||||||
|                             byteBlock.Reset(); |                             byteBlock.Reset(); | ||||||
|                             waitFinishedPackage.Package(byteBlock); |                             waitFinishedPackage.Package(byteBlock); | ||||||
|                             this.DmtpActor.Send(this.m_finishedFileResourceInfo_Response, byteBlock); |                             await this.DmtpActor.SendAsync(this.m_finishedFileResourceInfo_Response, byteBlock); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         waitFinishedPackage.UnpackageBody(byteBlock); |                         waitFinishedPackage.UnpackageBody(byteBlock); | ||||||
|                         Task.Factory.StartNew(this.RequestFinishedFileResourceInfo, waitFinishedPackage); |                         _ = this.RequestFinishedFileResourceInfo(waitFinishedPackage); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
| @@ -361,9 +357,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitFinishedPackage.UnpackageRouter(byteBlock); |                     waitFinishedPackage.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitFinishedPackage.Route) |                     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 |                     else | ||||||
| @@ -386,11 +382,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitSmallFilePackage.UnpackageRouter(byteBlock); |                     waitSmallFilePackage.UnpackageRouter(byteBlock); | ||||||
|                     if (waitSmallFilePackage.Route && this.DmtpActor.AllowRoute) |                     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; |                                 return true; | ||||||
|                             } |                             } | ||||||
|                             else |                             else | ||||||
| @@ -405,12 +401,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                         byteBlock.Reset(); |                         byteBlock.Reset(); | ||||||
|                         waitSmallFilePackage.SwitchId(); |                         waitSmallFilePackage.SwitchId(); | ||||||
|                         waitSmallFilePackage.Package(byteBlock); |                         waitSmallFilePackage.Package(byteBlock); | ||||||
|                         this.DmtpActor.Send(this.m_pullSmallFile_Response, byteBlock); |                         await this.DmtpActor.SendAsync(this.m_pullSmallFile_Response, byteBlock); | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         waitSmallFilePackage.UnpackageBody(byteBlock); |                         waitSmallFilePackage.UnpackageBody(byteBlock); | ||||||
|                         Task.Factory.StartNew(this.RequestPullSmallFile, waitSmallFilePackage); |                         _ = Task.Factory.StartNew(this.RequestPullSmallFile, waitSmallFilePackage); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
| @@ -427,9 +423,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitSmallFilePackage.UnpackageRouter(byteBlock); |                     waitSmallFilePackage.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && waitSmallFilePackage.Route) |                     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 |                     else | ||||||
| @@ -452,11 +448,11 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                     waitSmallFilePackage.UnpackageRouter(byteBlock); |                     waitSmallFilePackage.UnpackageRouter(byteBlock); | ||||||
|                     if (waitSmallFilePackage.Route && this.DmtpActor.AllowRoute) |                     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; |                                 return true; | ||||||
|                             } |                             } | ||||||
|                             else |                             else | ||||||
| @@ -472,12 +468,12 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                         byteBlock.Reset(); |                         byteBlock.Reset(); | ||||||
|                         waitSmallFilePackage.SwitchId(); |                         waitSmallFilePackage.SwitchId(); | ||||||
|                         waitSmallFilePackage.Package(byteBlock); |                         waitSmallFilePackage.Package(byteBlock); | ||||||
|                         this.DmtpActor.Send(this.m_pushSmallFile_Response, byteBlock); |                         await this.DmtpActor.SendAsync(this.m_pushSmallFile_Response, byteBlock); | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         waitSmallFilePackage.UnpackageBody(byteBlock); |                         waitSmallFilePackage.UnpackageBody(byteBlock); | ||||||
|                         Task.Factory.StartNew(this.RequestPushSmallFile, waitSmallFilePackage); |                         _ = this.RequestPushSmallFile(waitSmallFilePackage); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
| @@ -495,9 +491,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|  |  | ||||||
|                     if (this.DmtpActor.AllowRoute && waitSmallFilePackage.Route) |                     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 |                     else | ||||||
| @@ -568,24 +564,20 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|             return this.FileController.GetFullPath(this.m_rootPath, path); |             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) |             if (targetId == this.DmtpActor.Id) | ||||||
|             { |             { | ||||||
|                 rpcActor = this; |                 return this; | ||||||
|                 return true; |  | ||||||
|             } |             } | ||||||
|             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 newActor; | ||||||
|                     return true; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             return default; | ||||||
|             rpcActor = default; |  | ||||||
|             return false; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region Id传输 |         #region Id传输 | ||||||
| @@ -598,9 +590,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 return this.PrivateFinishedFileResourceInfo(targetId, fileResourceInfo, code, metadata, timeout, token); |                 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 |             else | ||||||
|             { |             { | ||||||
| @@ -625,9 +617,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 return this.PrivatePullFileResourceInfo(targetId, path, metadata, fileSectionSize, timeout, token); |                 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 |             else | ||||||
|             { |             { | ||||||
| @@ -652,9 +644,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 return this.PrivatePullFileSection(targetId, fileSection, timeout, token); |                 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 |             else | ||||||
|             { |             { | ||||||
| @@ -679,9 +671,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 return this.PrivatePushFileResourceInfo(targetId, savePath, fileResourceLocator, metadata, timeout, token); |                 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 |             else | ||||||
|             { |             { | ||||||
| @@ -715,9 +707,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 return this.PrivatePushFileSection(targetId, fileResourceLocator, fileSection, timeout, token); |                 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 |             else | ||||||
|             { |             { | ||||||
| @@ -1261,7 +1253,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 { |                 { | ||||||
|                     waitFinishedPackage.SwitchId(); |                     waitFinishedPackage.SwitchId(); | ||||||
|                     waitFinishedPackage.Package(byteBlock); |                     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) |                 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.SwitchId(); | ||||||
|                     waitFileResource.Package(byteBlock); |                     waitFileResource.Package(byteBlock); | ||||||
|                     this.DmtpActor.Send(this.m_pushFileResourceInfo_Response, byteBlock); |                     await this.DmtpActor.SendAsync(this.m_pushFileResourceInfo_Response, byteBlock); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             catch |             catch | ||||||
| @@ -1528,7 +1520,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public PullSmallFileResult PullSmallFile(string targetId, string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) |         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); |                 return actor.PullSmallFile(path, metadata, timeout, token); | ||||||
|             } |             } | ||||||
| @@ -1565,9 +1557,9 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public Result PushSmallFile(string targetId, string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) |         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 |             else | ||||||
|             { |             { | ||||||
| @@ -1827,7 +1819,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 { |                 { | ||||||
|                     waitSmallFilePackage.SwitchId(); |                     waitSmallFilePackage.SwitchId(); | ||||||
|                     waitSmallFilePackage.Package(byteBlock); |                     waitSmallFilePackage.Package(byteBlock); | ||||||
|                     this.DmtpActor.Send(this.m_pullSmallFile_Response, byteBlock); |                     await this.DmtpActor.SendAsync(this.m_pullSmallFile_Response, byteBlock); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 var resultArgs = new FileTransferedEventArgs( |                 var resultArgs = new FileTransferedEventArgs( | ||||||
| @@ -1891,7 +1883,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
|                 { |                 { | ||||||
|                     waitSmallFilePackage.Package(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( |                 var resultArgs = new FileTransferedEventArgs( | ||||||
|   | |||||||
| @@ -59,12 +59,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public int TryCount { get; set; } = 10; |         public int TryCount { get; set; } = 10; | ||||||
|  |  | ||||||
|         /// <summary> |         internal Result SetResult(Result result) | ||||||
|         /// 设置结果状态 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="result"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public Result SetResult(Result result) |  | ||||||
|         { |         { | ||||||
|             this.Result = result; |             this.Result = result; | ||||||
|             return result; |             return result; | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) |         public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             var smtpFileTransferActor = new DmtpFileTransferActor(client.DmtpActor) |             var dmtpFileTransferActor = new DmtpFileTransferActor(client.DmtpActor) | ||||||
|             { |             { | ||||||
|                 FileController = this.m_fileResourceController, |                 FileController = this.m_fileResourceController, | ||||||
|                 OnFileTransfering = this.OnFileTransfering, |                 OnFileTransfering = this.OnFileTransfering, | ||||||
| @@ -56,25 +56,25 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|                 RootPath = this.RootPath, |                 RootPath = this.RootPath, | ||||||
|                 MaxSmallFileLength = this.MaxSmallFileLength |                 MaxSmallFileLength = this.MaxSmallFileLength | ||||||
|             }; |             }; | ||||||
|             smtpFileTransferActor.SetProtocolFlags(this.StartProtocol); |             dmtpFileTransferActor.SetProtocolFlags(this.StartProtocol); | ||||||
|             client.DmtpActor.SetDmtpFileTransferActor(smtpFileTransferActor); |             client.DmtpActor.SetDmtpFileTransferActor(dmtpFileTransferActor); | ||||||
|  |  | ||||||
|             return e.InvokeNext(); |             return e.InvokeNext(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <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; |                     e.Handled = true; | ||||||
|                     return EasyTask.CompletedTask; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return e.InvokeNext(); |             await e.InvokeNext(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc cref="IDmtpFileTransferActor.MaxSmallFileLength"/> |         /// <inheritdoc cref="IDmtpFileTransferActor.MaxSmallFileLength"/> | ||||||
|   | |||||||
| @@ -48,21 +48,21 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpFileTransferActor"/> |         /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpFileTransferActor"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         /// <returns></returns> |         /// <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> |         /// <summary> | ||||||
|         /// 向<see cref="DmtpActor"/>中设置<see cref="DmtpFileTransferActor"/> |         /// 向<see cref="DmtpActor"/>中设置<see cref="DmtpFileTransferActor"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         /// <param name="smtpRpcActor"></param> |         /// <param name="dmtpRpcActor"></param> | ||||||
|         internal static void SetDmtpFileTransferActor(this IDmtpActor smtpActor, DmtpFileTransferActor smtpRpcActor) |         internal static void SetDmtpFileTransferActor(this IDmtpActor dmtpActor, DmtpFileTransferActor dmtpRpcActor) | ||||||
|         { |         { | ||||||
|             smtpActor.SetValue(DmtpFileTransferActorProperty, smtpRpcActor); |             dmtpActor.SetValue(DmtpFileTransferActorProperty, dmtpRpcActor); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|   | |||||||
| @@ -22,10 +22,10 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// DmtpRedisActor |         /// DmtpRedisActor | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         public DmtpRedisActor(IDmtpActor smtpActor) |         public DmtpRedisActor(IDmtpActor dmtpActor) | ||||||
|         { |         { | ||||||
|             this.DmtpActor = smtpActor; |             this.DmtpActor = dmtpActor; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
| @@ -241,7 +241,7 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="message"></param> |         /// <param name="message"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public bool InputReceivedData(DmtpMessage message) |         public async Task<bool> InputReceivedData(DmtpMessage message) | ||||||
|         { |         { | ||||||
|             if (message.ProtocolFlags == this.m_redis_Request) |             if (message.ProtocolFlags == this.m_redis_Request) | ||||||
|             { |             { | ||||||
| @@ -311,7 +311,7 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | |||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
|                 { |                 { | ||||||
|                     waitResult.Package(byteBlock); |                     waitResult.Package(byteBlock); | ||||||
|                     this.DmtpActor.Send(this.m_redis_Response, byteBlock); |                     await this.DmtpActor.SendAsync(this.m_redis_Response, byteBlock); | ||||||
|                 } |                 } | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ | |||||||
| //  感谢您的下载和使用 | //  感谢您的下载和使用 | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |  | ||||||
| using ThingsGateway.Foundation.Resources; | using ThingsGateway.Foundation.Resources; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Foundation.Dmtp.Redis | namespace ThingsGateway.Foundation.Dmtp.Redis | ||||||
| @@ -52,16 +54,16 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 从<see cref="DmtpActor"/>中获得<see cref="IDmtpRedisActor"/> |         /// 从<see cref="DmtpActor"/>中获得<see cref="IDmtpRedisActor"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         /// <returns></returns> |         /// <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> |         /// <summary> | ||||||
|   | |||||||
| @@ -58,30 +58,30 @@ namespace ThingsGateway.Foundation.Dmtp.Redis | |||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) |         public Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e) | ||||||
|         { |         { | ||||||
|             var smtpRedisActor = new DmtpRedisActor(client.DmtpActor) |             var dmtpRedisActor = new DmtpRedisActor(client.DmtpActor) | ||||||
|             { |             { | ||||||
|                 ICache = this.ICache, |                 ICache = this.ICache, | ||||||
|                 Converter = this.Converter |                 Converter = this.Converter | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             smtpRedisActor.SetProtocolFlags(this.StartProtocol); |             dmtpRedisActor.SetProtocolFlags(this.StartProtocol); | ||||||
|             client.DmtpActor.SetStmpRedisActor(smtpRedisActor); |             client.DmtpActor.SetStmpRedisActor(dmtpRedisActor); | ||||||
|  |  | ||||||
|             return e.InvokeNext(); |             return e.InvokeNext(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) |         public async Task OnDmtpReceived(IDmtpActorObject client, DmtpMessageEventArgs e) | ||||||
|         { |         { | ||||||
|             if (client.DmtpActor.GetDmtpRedisActor() is DmtpRedisActor redisClient) |             if (client.DmtpActor.GetDmtpRedisActor() is DmtpRedisActor redisClient) | ||||||
|             { |             { | ||||||
|                 if (redisClient.InputReceivedData(e.DmtpMessage)) |                 if (await redisClient.InputReceivedData(e.DmtpMessage)) | ||||||
|                 { |                 { | ||||||
|                     e.Handled = true; |                     e.Handled = true; | ||||||
|                     return EasyTask.CompletedTask; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return e.InvokeNext(); |             await e.InvokeNext(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|   | |||||||
| @@ -36,10 +36,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 创建一个DmtpRpcActor |         /// 创建一个DmtpRpcActor | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         public DmtpRpcActor(IDmtpActor smtpActor) |         public DmtpRpcActor(IDmtpActor dmtpActor) | ||||||
|         { |         { | ||||||
|             this.DmtpActor = smtpActor; |             this.DmtpActor = dmtpActor; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
| @@ -69,7 +69,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="message"></param> |         /// <param name="message"></param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public bool InputReceivedData(DmtpMessage message) |         public async Task<bool> InputReceivedData(DmtpMessage message) | ||||||
|         { |         { | ||||||
|             var byteBlock = message.BodyByteBlock; |             var byteBlock = message.BodyByteBlock; | ||||||
|  |  | ||||||
| @@ -77,14 +77,13 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|             { |             { | ||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
|                     //Console.WriteLine(byteBlock.Len); |  | ||||||
|                     var rpcPackage = new DmtpRpcPackage(); |                     var rpcPackage = new DmtpRpcPackage(); | ||||||
|                     rpcPackage.UnpackageRouter(byteBlock); |                     rpcPackage.UnpackageRouter(byteBlock); | ||||||
|                     if (rpcPackage.Route && this.DmtpActor.AllowRoute) |                     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); |                                 actor.Send(this.m_invoke_Request, byteBlock); | ||||||
|                                 return true; |                                 return true; | ||||||
| @@ -108,8 +107,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         rpcPackage.UnpackageBody(byteBlock); |                         rpcPackage.UnpackageBody(byteBlock); | ||||||
|                         Task.Factory.StartNew(this.InvokeThis, rpcPackage); |                         _ = Task.Factory.StartNew(this.InvokeThis, rpcPackage); | ||||||
|                         //this.InvokeThis(rpcPackage); |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch (Exception ex) |                 catch (Exception ex) | ||||||
| @@ -126,7 +124,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     rpcPackage.UnpackageRouter(byteBlock); |                     rpcPackage.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && rpcPackage.Route) |                     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); |                             actor.Send(this.m_invoke_Response, byteBlock); | ||||||
|                         } |                         } | ||||||
| @@ -151,7 +149,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     canceledPackage.UnpackageRouter(byteBlock); |                     canceledPackage.UnpackageRouter(byteBlock); | ||||||
|                     if (this.DmtpActor.AllowRoute && canceledPackage.Route) |                     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); |                             actor.Send(this.m_cancelInvoke, byteBlock); | ||||||
|                         } |                         } | ||||||
| @@ -203,7 +201,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var rpcPackage = (DmtpRpcPackage)o; |                 var rpcPackage = (DmtpRpcPackage)o; | ||||||
|                 //Console.WriteLine(rpcPackage.MethodName); |  | ||||||
|                 var psData = rpcPackage.ParametersBytes; |                 var psData = rpcPackage.ParametersBytes; | ||||||
|                 if (rpcPackage.Feedback == FeedbackType.WaitSend) |                 if (rpcPackage.Feedback == FeedbackType.WaitSend) | ||||||
|                 { |                 { | ||||||
| @@ -227,7 +225,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                 var invokeResult = new InvokeResult(); |                 var invokeResult = new InvokeResult(); | ||||||
|                 object[] ps = null; |                 object[] ps = null; | ||||||
|                 var methodInstance = this.GetInvokeMethod?.Invoke(rpcPackage.MethodName); |                 var methodInstance = this.GetInvokeMethod.Invoke(rpcPackage.MethodName); | ||||||
|                 DmtpRpcCallContext callContext = null; |                 DmtpRpcCallContext callContext = null; | ||||||
|                 if (methodInstance != null) |                 if (methodInstance != null) | ||||||
|                 { |                 { | ||||||
| @@ -242,7 +240,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                                 DmtpRpcPackage = rpcPackage |                                 DmtpRpcPackage = rpcPackage | ||||||
|                             }; |                             }; | ||||||
|                             this.TryAdd(rpcPackage.Sign, callContext); |                             this.TryAdd(rpcPackage.Sign, callContext); | ||||||
|                             if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) |                             if (methodInstance.IncludeCallContext) | ||||||
|                             { |                             { | ||||||
|                                 ps = new object[methodInstance.ParameterTypes.Length]; |                                 ps = new object[methodInstance.ParameterTypes.Length]; | ||||||
|                                 ps[0] = callContext; |                                 ps[0] = callContext; | ||||||
| @@ -283,7 +281,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     { |                     { | ||||||
|                         transientRpcServer.CallContext = callContext; |                         transientRpcServer.CallContext = callContext; | ||||||
|                     } |                     } | ||||||
|                     invokeResult = await RpcStore.ExecuteAsync(rpcServer, ps, callContext); |                     invokeResult = await RpcStore.ExecuteAsync(rpcServer, ps, callContext).ConfigureFalseAwait(); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (rpcPackage.Feedback == FeedbackType.OnlySend) |                 if (rpcPackage.Feedback == FeedbackType.OnlySend) | ||||||
| @@ -316,7 +314,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                                 rpcPackage.ParametersBytes = new List<byte[]>(); |                                 rpcPackage.ParametersBytes = new List<byte[]>(); | ||||||
|  |  | ||||||
|                                 var i = 0; |                                 var i = 0; | ||||||
|                                 if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext)) |                                 if (methodInstance.IncludeCallContext) | ||||||
|                                 { |                                 { | ||||||
|                                     i = 1; |                                     i = 1; | ||||||
|                                 } |                                 } | ||||||
| @@ -369,24 +367,37 @@ 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) |             if (targetId == this.DmtpActor.Id) | ||||||
|             { |             { | ||||||
|                 rpcActor = this; |                 return this; | ||||||
|                 return true; |  | ||||||
|             } |             } | ||||||
|             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 newActor; | ||||||
|                     return true; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             return default; | ||||||
|  |         } | ||||||
|  |  | ||||||
|             rpcActor = default; |         private static void CheckWaitDataStatus(WaitDataStatus status) | ||||||
|             return false; |         { | ||||||
|  |             switch (status) | ||||||
|  |             { | ||||||
|  |                 case WaitDataStatus.SetRunning: | ||||||
|  |                     return; | ||||||
|  |                 case WaitDataStatus.Canceled: throw new OperationCanceledException(); | ||||||
|  |                 case WaitDataStatus.Overtime: throw new TimeoutException(); | ||||||
|  |                 case WaitDataStatus.Disposed: | ||||||
|  |                 case WaitDataStatus.Default: | ||||||
|  |                 default: | ||||||
|  |                     { | ||||||
|  |                         throw new Exception(TouchSocketCoreResource.UnknownError.GetDescription()); | ||||||
|  |                     } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region Rpc |         #region Rpc | ||||||
| @@ -435,53 +446,33 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.SetRunning: |  | ||||||
|                                     { |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |                             return returnType.GetDefault(); | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|  |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|  |                             resultContext.ThrowStatus(); | ||||||
|  |                             if (resultContext.IsByRef) | ||||||
|                             { |                             { | ||||||
|                                 case WaitDataStatus.SetRunning: |                                 try | ||||||
|  |                                 { | ||||||
|  |                                     for (var i = 0; i < parameters.Length; i++) | ||||||
|                                     { |                                     { | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |                                         parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         if (resultContext.IsByRef) |  | ||||||
|                                         { |  | ||||||
|                                             try |  | ||||||
|                                             { |  | ||||||
|                                                 for (var i = 0; i < parameters.Length; i++) |  | ||||||
|                                                 { |  | ||||||
|                                                     parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); |  | ||||||
|                                                 } |  | ||||||
|                                             } |  | ||||||
|                                             catch (Exception e) |  | ||||||
|                                             { |  | ||||||
|                                                 throw new Exception(e.Message); |  | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                         else |  | ||||||
|                                         { |  | ||||||
|                                             parameters = null; |  | ||||||
|                                         } |  | ||||||
|                                         return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |                                     } | ||||||
|  |                                 } | ||||||
|  |                                 catch (Exception e) | ||||||
|  |                                 { | ||||||
|  |                                     throw new Exception(e.Message); | ||||||
|  |                                 } | ||||||
|                             } |                             } | ||||||
|                             return returnType.GetDefault(); |                             else | ||||||
|  |                             { | ||||||
|  |                                 parameters = null; | ||||||
|  |                             } | ||||||
|  |                             return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); | ||||||
|                         } |                         } | ||||||
|                     default: |                     default: | ||||||
|                         return returnType.GetDefault(); |                         return returnType.GetDefault(); | ||||||
| @@ -504,8 +495,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -532,7 +521,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -540,44 +528,24 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.SetRunning: |  | ||||||
|                                     { |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|  |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|  |                             resultContext.ThrowStatus(); | ||||||
|  |                             if (resultContext.IsByRef) | ||||||
|                             { |                             { | ||||||
|                                 case WaitDataStatus.SetRunning: |                                 for (var i = 0; i < parameters.Length; i++) | ||||||
|                                     { |                                 { | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |                                     parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); | ||||||
|                                         resultContext.ThrowStatus(); |                                 } | ||||||
|                                         if (resultContext.IsByRef) |                             } | ||||||
|                                         { |                             else | ||||||
|                                             for (var i = 0; i < parameters.Length; i++) |                             { | ||||||
|                                             { |                                 parameters = null; | ||||||
|                                                 parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); |  | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                         else |  | ||||||
|                                         { |  | ||||||
|                                             parameters = null; |  | ||||||
|                                         } |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |                             } | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
| @@ -639,33 +607,14 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.SetRunning: |  | ||||||
|                                     break; |  | ||||||
|  |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |  | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     default: |                     default: | ||||||
| @@ -689,8 +638,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetWaitData(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -722,7 +669,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -731,31 +677,15 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |                             return returnType.GetDefault(); | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |                             return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |  | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                     default: |                     default: | ||||||
| @@ -779,8 +709,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetWaitDataAsync(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetWaitDataAsync(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -808,7 +736,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     rpcPackage.Package(byteBlock); |                     rpcPackage.Package(byteBlock); | ||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     await this.DmtpActor.SendAsync(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
| @@ -818,33 +746,14 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.SetRunning: |  | ||||||
|                                     break; |  | ||||||
|  |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |  | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     default: |                     default: | ||||||
| @@ -895,10 +804,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     rpcPackage.Package(byteBlock); |                     rpcPackage.Package(byteBlock); | ||||||
|  |  | ||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     await this.DmtpActor.SendAsync(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -907,31 +815,15 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |                             return returnType.GetDefault(); | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |                             return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |  | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                     default: |                     default: | ||||||
| @@ -961,7 +853,7 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); |                 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); |                 actor.Invoke(invokeKey, invokeOption, parameters); | ||||||
|                 return; |                 return; | ||||||
| @@ -977,7 +869,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -1009,7 +900,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -1017,33 +907,14 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.SetRunning: |  | ||||||
|                                     break; |  | ||||||
|  |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |  | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     default: |                     default: | ||||||
| @@ -1069,9 +940,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); |                 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 |             var rpcPackage = new DmtpRpcPackage | ||||||
| @@ -1084,10 +955,8 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|  |  | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
|                 { |                 { | ||||||
|                     if (invokeOption == default) |                     if (invokeOption == default) | ||||||
| @@ -1116,7 +985,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -1125,31 +993,15 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |                             return returnType.GetDefault(); | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |                             return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |  | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                     default: |                     default: | ||||||
| @@ -1175,9 +1027,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); |                 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; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -1191,7 +1043,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -1219,7 +1070,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -1228,40 +1078,24 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return; |                             return; | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|  |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|  |                             resultContext.ThrowStatus(); | ||||||
|  |                             if (resultContext.IsByRef) | ||||||
|                             { |                             { | ||||||
|                                 case WaitDataStatus.SetRunning: |                                 for (var i = 0; i < parameters.Length; i++) | ||||||
|                                     { |                                 { | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |                                     parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); | ||||||
|                                         resultContext.ThrowStatus(); |                                 } | ||||||
|                                         if (resultContext.IsByRef) |                             } | ||||||
|                                         { |                             else | ||||||
|                                             for (var i = 0; i < parameters.Length; i++) |                             { | ||||||
|                                             { |                                 parameters = null; | ||||||
|                                                 parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); |  | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                         else |  | ||||||
|                                         { |  | ||||||
|                                             parameters = null; |  | ||||||
|                                         } |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |                             } | ||||||
|                             return; |                             return; | ||||||
|                         } |                         } | ||||||
| @@ -1289,9 +1123,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); |                 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 |             var rpcPackage = new DmtpRpcPackage | ||||||
| @@ -1304,7 +1138,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitData(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -1330,7 +1163,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -1339,42 +1171,26 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |                             return returnType.GetDefault(); | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (waitData.Wait(invokeOption.Timeout)) |                             CheckWaitDataStatus(waitData.Wait(invokeOption.Timeout)); | ||||||
|  |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|  |                             resultContext.ThrowStatus(); | ||||||
|  |                             if (resultContext.IsByRef) | ||||||
|                             { |                             { | ||||||
|                                 case WaitDataStatus.SetRunning: |                                 for (var i = 0; i < parameters.Length; i++) | ||||||
|                                     { |                                 { | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |                                     parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); | ||||||
|                                         resultContext.ThrowStatus(); |                                 } | ||||||
|                                         if (resultContext.IsByRef) |  | ||||||
|                                         { |  | ||||||
|                                             for (var i = 0; i < parameters.Length; i++) |  | ||||||
|                                             { |  | ||||||
|                                                 parameters[i] = this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ParametersBytes[i], types[i]); |  | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                         else |  | ||||||
|                                         { |  | ||||||
|                                             parameters = null; |  | ||||||
|                                         } |  | ||||||
|                                         return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |                             } | ||||||
|                             return returnType.GetDefault(); |                             else | ||||||
|  |                             { | ||||||
|  |                                 parameters = null; | ||||||
|  |                             } | ||||||
|  |                             return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                     default: |                     default: | ||||||
| @@ -1400,9 +1216,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); |                 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; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -1416,7 +1232,6 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitDataAsync(rpcPackage); |             var waitData = this.DmtpActor.WaitHandlePool.GetReverseWaitDataAsync(rpcPackage); | ||||||
|  |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
| @@ -1445,10 +1260,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     rpcPackage.Package(byteBlock); |                     rpcPackage.Package(byteBlock); | ||||||
|  |  | ||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     await this.DmtpActor.SendAsync(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -1456,33 +1270,14 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.SetRunning: |  | ||||||
|                                     break; |  | ||||||
|  |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |  | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         break; |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     default: |                     default: | ||||||
| @@ -1508,9 +1303,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                 throw new ArgumentException($"“{nameof(invokeKey)}”不能为 null 或空。", nameof(invokeKey)); |                 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 |             var rpcPackage = new DmtpRpcPackage | ||||||
| @@ -1550,11 +1345,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|                     rpcPackage.Package(byteBlock); |                     rpcPackage.Package(byteBlock); | ||||||
|  |  | ||||||
|                     this.DmtpActor.Send(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); |                     await this.DmtpActor.SendAsync(this.m_invoke_Request, byteBlock.Buffer, 0, byteBlock.Len); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|                 switch (invokeOption.FeedbackType) |                 switch (invokeOption.FeedbackType) | ||||||
|                 { |                 { | ||||||
|                     case FeedbackType.OnlySend: |                     case FeedbackType.OnlySend: | ||||||
| @@ -1563,31 +1356,15 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitSend: |                     case FeedbackType.WaitSend: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |                             return returnType.GetDefault(); | ||||||
|                         } |                         } | ||||||
|                     case FeedbackType.WaitInvoke: |                     case FeedbackType.WaitInvoke: | ||||||
|                         { |                         { | ||||||
|                             switch (await waitData.WaitAsync(invokeOption.Timeout)) |                             CheckWaitDataStatus(await waitData.WaitAsync(invokeOption.Timeout).ConfigureFalseAwait()); | ||||||
|                             { |                             var resultContext = (DmtpRpcPackage)waitData.WaitResult; | ||||||
|                                 case WaitDataStatus.SetRunning: |                             resultContext.ThrowStatus(); | ||||||
|                                     { |                             return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); | ||||||
|                                         var resultContext = (DmtpRpcPackage)waitData.WaitResult; |  | ||||||
|                                         resultContext.ThrowStatus(); |  | ||||||
|                                         return this.SerializationSelector.DeserializeParameter(resultContext.SerializationType, resultContext.ReturnParameterBytes, returnType); |  | ||||||
|                                     } |  | ||||||
|                                 case WaitDataStatus.Overtime: |  | ||||||
|                                     { |  | ||||||
|                                         throw new TimeoutException("等待结果超时"); |  | ||||||
|                                     } |  | ||||||
|                             } |  | ||||||
|                             return returnType.GetDefault(); |  | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                     default: |                     default: | ||||||
|   | |||||||
| @@ -42,11 +42,11 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpRpcActor"/> |         /// 从<see cref="DmtpActor"/>中获取<see cref="IDmtpRpcActor"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         /// <returns></returns> |         /// <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> |         /// <summary> | ||||||
| @@ -57,12 +57,12 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         /// <exception cref="ArgumentNullException"></exception> |         /// <exception cref="ArgumentNullException"></exception> | ||||||
|         public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActorObject client) |         public static IDmtpRpcActor GetDmtpRpcActor(this IDmtpActorObject client) | ||||||
|         { |         { | ||||||
|             var smtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); |             var dmtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); | ||||||
|             if (smtpRpcActor is null) |             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> |         /// <summary> | ||||||
| @@ -73,22 +73,22 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|         /// <exception cref="ArgumentNullException"></exception> |         /// <exception cref="ArgumentNullException"></exception> | ||||||
|         public static TDmtpRpcActor GetDmtpRpcActor<TDmtpRpcActor>(this IDmtpActorObject client) where TDmtpRpcActor : IDmtpRpcActor |         public static TDmtpRpcActor GetDmtpRpcActor<TDmtpRpcActor>(this IDmtpActorObject client) where TDmtpRpcActor : IDmtpRpcActor | ||||||
|         { |         { | ||||||
|             var smtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); |             var dmtpRpcActor = client.DmtpActor.GetDmtpRpcActor(); | ||||||
|             if (smtpRpcActor is null) |             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> |         /// <summary> | ||||||
|         /// 向<see cref="DmtpActor"/>中设置<see cref="IDmtpRpcActor"/> |         /// 向<see cref="DmtpActor"/>中设置<see cref="IDmtpRpcActor"/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="smtpActor"></param> |         /// <param name="dmtpActor"></param> | ||||||
|         /// <param name="smtpRpcActor"></param> |         /// <param name="dmtpRpcActor"></param> | ||||||
|         internal static void SetDmtpRpcActor(this IDmtpActor smtpActor, IDmtpRpcActor smtpRpcActor) |         internal static void SetDmtpRpcActor(this IDmtpActor dmtpActor, IDmtpRpcActor dmtpRpcActor) | ||||||
|         { |         { | ||||||
|             smtpActor.SetValue(DmtpRpcActorProperty, smtpRpcActor); |             dmtpActor.SetValue(DmtpRpcActorProperty, dmtpRpcActor); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #region 插件扩展 |         #region 插件扩展 | ||||||
|   | |||||||
| @@ -94,9 +94,9 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|             return this.ActionMap.GetMethodInstance(name); |             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配置 |         #region Rpc配置 | ||||||
| @@ -135,31 +135,30 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|             pluginsManager.Add<IDmtpActorObject, DmtpMessageEventArgs>(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this.OnDmtpReceived); |             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); |             var dmtpRpcActor = this.CreateDmtpRpcActor(client.DmtpActor); | ||||||
|             smtpRpcActor.RpcStore = this.RpcStore; |             dmtpRpcActor.RpcStore = this.RpcStore; | ||||||
|             smtpRpcActor.SerializationSelector = this.SerializationSelector; |             dmtpRpcActor.SerializationSelector = this.SerializationSelector; | ||||||
|             smtpRpcActor.GetInvokeMethod = this.GetInvokeMethod; |             dmtpRpcActor.GetInvokeMethod = this.GetInvokeMethod; | ||||||
|  |  | ||||||
|             smtpRpcActor.SetProtocolFlags(this.StartProtocol); |             dmtpRpcActor.SetProtocolFlags(this.StartProtocol); | ||||||
|             client.DmtpActor.SetDmtpRpcActor(smtpRpcActor); |             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; |                     e.Handled = true; | ||||||
|                     return EasyTask.CompletedTask; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             await e.InvokeNext(); | ||||||
|             return e.InvokeNext(); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion Config |         #endregion Config | ||||||
|   | |||||||
| @@ -108,10 +108,10 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc | |||||||
|  |  | ||||||
|         internal void LoadInvokeOption(IInvokeOption option) |         internal void LoadInvokeOption(IInvokeOption option) | ||||||
|         { |         { | ||||||
|             if (option is DmtpInvokeOption smtpInvokeOption) |             if (option is DmtpInvokeOption dmtpInvokeOption) | ||||||
|             { |             { | ||||||
|                 this.Feedback = smtpInvokeOption.FeedbackType; |                 this.Feedback = dmtpInvokeOption.FeedbackType; | ||||||
|                 this.SerializationType = smtpInvokeOption.SerializationType; |                 this.SerializationType = dmtpInvokeOption.SerializationType; | ||||||
|             } |             } | ||||||
|             else if (option is InvokeOption invokeOption) |             else if (option is InvokeOption invokeOption) | ||||||
|             { |             { | ||||||
|   | |||||||
| @@ -27,6 +27,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="message"></param> |         /// <param name="message"></param> | ||||||
|         /// <returns>当满足本协议时,应当返回<see langword="true"/>,其他时候应该返回<see langword="false"/>.</returns> |         /// <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++; |                         failedCount++; | ||||||
|                         if (failedCount > this.MaxFailCount) |                         if (failedCount > this.MaxFailCount) | ||||||
|                         { |                         { | ||||||
|                             client.DmtpActor.Close(true, "自动心跳失败次数达到最大,已断开连接。"); |                             client.DmtpActor.Close("自动心跳失败次数达到最大,已断开连接。"); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -18,8 +18,8 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|     public class DmtpRouteService : IDmtpRouteService |     public class DmtpRouteService : IDmtpRouteService | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 查找路由的委托 |         /// <inheritdoc/> | ||||||
|         /// </summary> |         /// </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> |         /// </summary> | ||||||
|         /// <param name="container"></param> |         /// <param name="container"></param> | ||||||
|         /// <param name="func"></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() |             container.RegisterSingleton<IDmtpRouteService>(new DmtpRouteService() | ||||||
|             { |             { | ||||||
|                 FindDmtpActor = func |                 FindDmtpActor = func | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 添加基于设定委托的Dmtp路由服务。 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="container"></param> | ||||||
|  |         /// <param name="action"></param> | ||||||
|  |         public static void AddDmtpRouteService(this IContainer container, Func<string, IDmtpActor> action) | ||||||
|  |         { | ||||||
|  |             AddDmtpRouteService(container, async (id) => | ||||||
|  |             { | ||||||
|  |                 await EasyTask.CompletedTask; | ||||||
|  |                 return action.Invoke(id); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -20,6 +20,6 @@ namespace ThingsGateway.Foundation.Dmtp | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 查找其他IDmtpActor |         /// 查找其他IDmtpActor | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         Func<string, IDmtpActor> FindDmtpActor { get; set; } |         Func<string, Task<IDmtpActor>> FindDmtpActor { get; set; } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -22,6 +22,7 @@ | |||||||
| //  感谢您的下载和使用 | //  感谢您的下载和使用 | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Web; | using System.Web; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -134,12 +134,12 @@ namespace ThingsGateway.Foundation.Http | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 相对路径(不含参数) |         /// 相对路径(不含参数) | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public string RelativeURL { get; private set; } |         public string RelativeURL { get; private set; } = "/"; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Url全地址,包含参数 |         /// Url全地址,包含参数 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public string URL { get; private set; } |         public string URL { get; private set; } = "/"; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///  构建响应数据。 |         ///  构建响应数据。 | ||||||
| @@ -175,28 +175,26 @@ namespace ThingsGateway.Foundation.Http | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 设置Url,必须以“/”开头,可带参数 |         /// 设置Url,可带参数 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="url"></param> |         /// <param name="url"></param> | ||||||
|         /// <param name="justValue"></param> |  | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public HttpRequest SetUrl(string url, bool justValue = false) |         public HttpRequest SetUrl(string url) | ||||||
|         { |         { | ||||||
|             this.URL = justValue || url.StartsWith("/") ? url : "/" + url; |             this.URL = url.StartsWith("/") ? url : $"/{url}"; | ||||||
|             this.ParseUrl(); |             this.ParseUrl(); | ||||||
|             return this; |             return this; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 输出 |         /// 设置代理Host | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public override string ToString() |         /// <param name="host"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public HttpRequest SetProxyHost(string host) | ||||||
|         { |         { | ||||||
|             using (var byteBlock = new ByteBlock()) |             this.URL = host; | ||||||
|             { |             return this; | ||||||
|                 this.Build(byteBlock); |  | ||||||
|                 return byteBlock.ToString(); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -412,7 +410,17 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                 } |                 } | ||||||
|                 if (urls.Length > 1) |                 if (urls.Length > 1) | ||||||
|                 { |                 { | ||||||
|                     this.m_query = GetParameters(urls[1]); |                     if (this.m_query == null) | ||||||
|  |                     { | ||||||
|  |                         this.m_query = GetParameters(urls[1]); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         foreach (var item in GetParameters(urls[1])) | ||||||
|  |                         { | ||||||
|  |                             this.m_query.Add(item.Key, item.Value); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
| @@ -420,5 +428,17 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                 this.RelativeURL = this.URL; |                 this.RelativeURL = this.URL; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 输出 | ||||||
|  |         /// </summary> | ||||||
|  |         public override string ToString() | ||||||
|  |         { | ||||||
|  |             using (var byteBlock = new ByteBlock()) | ||||||
|  |             { | ||||||
|  |                 this.Build(byteBlock); | ||||||
|  |                 return byteBlock.ToString(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -196,6 +196,18 @@ namespace ThingsGateway.Foundation.Http | |||||||
|             this.Responsed = responsed; |             this.Responsed = responsed; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 输出 | ||||||
|  |         /// </summary> | ||||||
|  |         public override string ToString() | ||||||
|  |         { | ||||||
|  |             using (var byteBlock = new ByteBlock()) | ||||||
|  |             { | ||||||
|  |                 this.Build(byteBlock, false); | ||||||
|  |                 return byteBlock.ToString(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 构建数据为字节数组。 |         /// 构建数据为字节数组。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|   | |||||||
| @@ -38,24 +38,17 @@ namespace ThingsGateway.Foundation.Http | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class HttpClientBase : TcpClientBase, IHttpClient |     public class HttpClientBase : TcpClientBase, IHttpClient | ||||||
|     { |     { | ||||||
|         private readonly object m_requestLocker = new object(); |         #region 字段 | ||||||
|         private readonly WaitData<HttpResponse> m_waitData; |  | ||||||
|  |         private readonly SemaphoreSlim m_semaphoreForRequest = new SemaphoreSlim(1, 1); | ||||||
|  |         private readonly WaitData<HttpResponse> m_waitData = new WaitData<HttpResponse>(); | ||||||
|  |         private readonly WaitDataAsync<HttpResponse> m_waitDataAsync = new WaitDataAsync<HttpResponse>(); | ||||||
|         private bool m_getContent; |         private bool m_getContent; | ||||||
|  |  | ||||||
|         /// <summary> |         #endregion 字段 | ||||||
|         /// 构造函数 |  | ||||||
|         /// </summary> |  | ||||||
|         public HttpClientBase() |  | ||||||
|         { |  | ||||||
|             this.m_waitData = new WaitData<HttpResponse>(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |         public override void Connect(int timeout, CancellationToken token) | ||||||
|         /// <param name="timeout"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public override ITcpClient Connect(int timeout = 5000) |  | ||||||
|         { |         { | ||||||
|             if (this.Config.GetValue(HttpConfigExtensions.HttpProxyProperty) is HttpProxy httpProxy) |             if (this.Config.GetValue(HttpConfigExtensions.HttpProxyProperty) is HttpProxy httpProxy) | ||||||
|             { |             { | ||||||
| @@ -65,13 +58,13 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
|                     this.Config.SetRemoteIPHost(proxyHost); |                     this.Config.SetRemoteIPHost(proxyHost); | ||||||
|                     base.Connect(timeout); |                     base.Connect(timeout, token); | ||||||
|                     var request = new HttpRequest(); |                     var request = new HttpRequest(); | ||||||
|                     request.InitHeaders() |                     request.InitHeaders() | ||||||
|                         .SetHost(remoteHost.Host) |                         .SetHost(remoteHost.Host) | ||||||
|                         .SetUrl(remoteHost.Host, true) |                         .SetProxyHost(remoteHost.Host) | ||||||
|                         .AsMethod("CONNECT"); |                         .AsMethod("CONNECT"); | ||||||
|                     var response = this.Request(request, timeout: timeout); |                     var response = this.Request(request, false, timeout, token); | ||||||
|                     if (response.IsProxyAuthenticationRequired) |                     if (response.IsProxyAuthenticationRequired) | ||||||
|                     { |                     { | ||||||
|                         if (credential is null) |                         if (credential is null) | ||||||
| @@ -90,10 +83,10 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                         if (!response.KeepAlive) |                         if (!response.KeepAlive) | ||||||
|                         { |                         { | ||||||
|                             base.Close("代理要求关闭连接,随后重写连接。"); |                             base.Close("代理要求关闭连接,随后重写连接。"); | ||||||
|                             base.Connect(timeout); |                             base.Connect(timeout, token); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         response = this.Request(request, timeout: timeout); |                         response = this.Request(request, false, timeout, token); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (response.StatusCode != 200) |                     if (response.StatusCode != 200) | ||||||
| @@ -108,37 +101,85 @@ namespace ThingsGateway.Foundation.Http | |||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 base.Connect(timeout); |                 base.Connect(timeout, token); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public override async Task ConnectAsync(int timeout, CancellationToken token) | ||||||
|  |         { | ||||||
|  |             if (this.Config.GetValue(HttpConfigExtensions.HttpProxyProperty) is HttpProxy httpProxy) | ||||||
|  |             { | ||||||
|  |                 var proxyHost = httpProxy.Host; | ||||||
|  |                 var credential = httpProxy.Credential; | ||||||
|  |                 var remoteHost = this.Config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty); | ||||||
|  |                 try | ||||||
|  |                 { | ||||||
|  |                     this.Config.SetRemoteIPHost(proxyHost); | ||||||
|  |                     await base.ConnectAsync(timeout, token); | ||||||
|  |                     var request = new HttpRequest(); | ||||||
|  |                     request.InitHeaders() | ||||||
|  |                         .SetHost(remoteHost.Host) | ||||||
|  |                         .SetProxyHost(remoteHost.Host) | ||||||
|  |                         .AsMethod("CONNECT"); | ||||||
|  |                     var response = await this.RequestAsync(request, false, timeout, token); | ||||||
|  |                     if (response.IsProxyAuthenticationRequired) | ||||||
|  |                     { | ||||||
|  |                         if (credential is null) | ||||||
|  |                         { | ||||||
|  |                             throw new Exception("未指定代理的凭据。"); | ||||||
|  |                         } | ||||||
|  |                         var authHeader = response.Headers.Get(HttpHeaders.ProxyAuthenticate); | ||||||
|  |                         if (authHeader.IsNullOrEmpty()) | ||||||
|  |                         { | ||||||
|  |                             throw new Exception("未指定代理身份验证质询。"); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         var ares = new AuthenticationChallenge(authHeader, credential); | ||||||
|  |  | ||||||
|  |                         request.Headers.Add(HttpHeaders.ProxyAuthorization, ares.ToString()); | ||||||
|  |                         if (!response.KeepAlive) | ||||||
|  |                         { | ||||||
|  |                             base.Close("代理要求关闭连接,随后重写连接。"); | ||||||
|  |                             await base.ConnectAsync(timeout, token); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         response = await this.RequestAsync(request, timeout: timeout); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     if (response.StatusCode != 200) | ||||||
|  |                     { | ||||||
|  |                         throw new Exception(response.StatusMessage); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 finally | ||||||
|  |                 { | ||||||
|  |                     this.Config.SetRemoteIPHost(remoteHost); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 await base.ConnectAsync(timeout, token); | ||||||
|             } |             } | ||||||
|             return this; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="request"><inheritdoc/></param> |  | ||||||
|         /// <param name="onlyRequest"><inheritdoc/></param> |  | ||||||
|         /// <param name="timeout"><inheritdoc/></param> |  | ||||||
|         /// <param name="token"><inheritdoc/></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public HttpResponse Request(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default) |         public HttpResponse Request(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default) | ||||||
|         { |         { | ||||||
|             lock (this.m_requestLocker) |             try | ||||||
|             { |             { | ||||||
|  |                 this.m_semaphoreForRequest.Wait(token); | ||||||
|                 this.m_getContent = false; |                 this.m_getContent = false; | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
|                 { |                 { | ||||||
|                     request.Build(byteBlock); |                     request.Build(byteBlock); | ||||||
|  |  | ||||||
|                     this.m_waitData.Reset(); |                     this.Reset(token); | ||||||
|                     this.m_waitData.SetCancellationToken(token); |  | ||||||
|  |  | ||||||
|                     this.DefaultSend(byteBlock); |                     this.DefaultSend(byteBlock); | ||||||
|                     if (onlyRequest) |                     if (onlyRequest) | ||||||
|                     { |                     { | ||||||
|                         return default; |                         return default; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     switch (this.m_waitData.Wait(timeout)) |                     switch (this.m_waitData.Wait(timeout)) | ||||||
|                     { |                     { | ||||||
|                         case WaitDataStatus.SetRunning: |                         case WaitDataStatus.SetRunning: | ||||||
| @@ -147,8 +188,7 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                         case WaitDataStatus.Overtime: |                         case WaitDataStatus.Overtime: | ||||||
|                             throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription()); |                             throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription()); | ||||||
|                         case WaitDataStatus.Canceled: |                         case WaitDataStatus.Canceled: | ||||||
|                             return default; |                             throw new OperationCanceledException(); | ||||||
|  |  | ||||||
|                         case WaitDataStatus.Default: |                         case WaitDataStatus.Default: | ||||||
|                         case WaitDataStatus.Disposed: |                         case WaitDataStatus.Disposed: | ||||||
|                         default: |                         default: | ||||||
| @@ -156,27 +196,62 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 this.m_semaphoreForRequest.Release(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public async Task<HttpResponse> RequestAsync(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 await this.m_semaphoreForRequest.WaitAsync(timeout, token); | ||||||
|  |                 this.m_getContent = false; | ||||||
|  |                 using (var byteBlock = new ByteBlock()) | ||||||
|  |                 { | ||||||
|  |                     request.Build(byteBlock); | ||||||
|  |  | ||||||
|  |                     this.Reset(token); | ||||||
|  |                     await this.DefaultSendAsync(byteBlock); | ||||||
|  |                     if (onlyRequest) | ||||||
|  |                     { | ||||||
|  |                         return default; | ||||||
|  |                     } | ||||||
|  |                     switch (await this.m_waitDataAsync.WaitAsync(timeout)) | ||||||
|  |                     { | ||||||
|  |                         case WaitDataStatus.SetRunning: | ||||||
|  |                             return this.m_waitDataAsync.WaitResult; | ||||||
|  |                         case WaitDataStatus.Overtime: | ||||||
|  |                             throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription()); | ||||||
|  |                         case WaitDataStatus.Canceled: | ||||||
|  |                             throw new OperationCanceledException(); | ||||||
|  |                         case WaitDataStatus.Default: | ||||||
|  |                         case WaitDataStatus.Disposed: | ||||||
|  |                         default: | ||||||
|  |                             throw new Exception(TouchSocketHttpResource.UnknownError.GetDescription()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 this.m_semaphoreForRequest.Release(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="request"></param> |  | ||||||
|         /// <param name="onlyRequest"></param> |  | ||||||
|         /// <param name="timeout"></param> |  | ||||||
|         /// <param name="token"></param> |  | ||||||
|         /// <returns></returns> |  | ||||||
|         public HttpResponse RequestContent(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default) |         public HttpResponse RequestContent(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default) | ||||||
|         { |         { | ||||||
|             lock (this.m_requestLocker) |             try | ||||||
|             { |             { | ||||||
|  |                 this.m_semaphoreForRequest.Wait(token); | ||||||
|                 this.m_getContent = true; |                 this.m_getContent = true; | ||||||
|                 using (var byteBlock = new ByteBlock()) |                 using (var byteBlock = new ByteBlock()) | ||||||
|                 { |                 { | ||||||
|                     request.Build(byteBlock); |                     request.Build(byteBlock); | ||||||
|  |  | ||||||
|                     this.m_waitData.Reset(); |                     this.Reset(token); | ||||||
|                     this.m_waitData.SetCancellationToken(token); |  | ||||||
|  |  | ||||||
|                     this.DefaultSend(byteBlock); |                     this.DefaultSend(byteBlock); | ||||||
|                     if (onlyRequest) |                     if (onlyRequest) | ||||||
| @@ -188,12 +263,10 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                     { |                     { | ||||||
|                         case WaitDataStatus.SetRunning: |                         case WaitDataStatus.SetRunning: | ||||||
|                             return this.m_waitData.WaitResult; |                             return this.m_waitData.WaitResult; | ||||||
|  |  | ||||||
|                         case WaitDataStatus.Overtime: |                         case WaitDataStatus.Overtime: | ||||||
|                             throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription()); |                             throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription()); | ||||||
|                         case WaitDataStatus.Canceled: |                         case WaitDataStatus.Canceled: | ||||||
|                             return default; |                             throw new OperationCanceledException(); | ||||||
|  |  | ||||||
|                         case WaitDataStatus.Default: |                         case WaitDataStatus.Default: | ||||||
|                         case WaitDataStatus.Disposed: |                         case WaitDataStatus.Disposed: | ||||||
|                         default: |                         default: | ||||||
| @@ -201,6 +274,50 @@ namespace ThingsGateway.Foundation.Http | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 this.m_semaphoreForRequest.Release(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public async Task<HttpResponse> RequestContentAsync(HttpRequest request, bool onlyRequest = false, int timeout = 10 * 1000, CancellationToken token = default) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 await this.m_semaphoreForRequest.WaitAsync(timeout, token); | ||||||
|  |                 this.m_getContent = true; | ||||||
|  |                 using (var byteBlock = new ByteBlock()) | ||||||
|  |                 { | ||||||
|  |                     request.Build(byteBlock); | ||||||
|  |  | ||||||
|  |                     this.Reset(token); | ||||||
|  |  | ||||||
|  |                     await this.DefaultSendAsync(byteBlock); | ||||||
|  |                     if (onlyRequest) | ||||||
|  |                     { | ||||||
|  |                         return default; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     switch (await this.m_waitDataAsync.WaitAsync(timeout)) | ||||||
|  |                     { | ||||||
|  |                         case WaitDataStatus.SetRunning: | ||||||
|  |                             return this.m_waitData.WaitResult; | ||||||
|  |                         case WaitDataStatus.Overtime: | ||||||
|  |                             throw new TimeoutException(TouchSocketHttpResource.Overtime.GetDescription()); | ||||||
|  |                         case WaitDataStatus.Canceled: | ||||||
|  |                             throw new OperationCanceledException(); | ||||||
|  |                         case WaitDataStatus.Default: | ||||||
|  |                         case WaitDataStatus.Disposed: | ||||||
|  |                         default: | ||||||
|  |                             throw new Exception(TouchSocketHttpResource.UnknownError.GetDescription()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 this.m_semaphoreForRequest.Release(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -213,22 +330,6 @@ namespace ThingsGateway.Foundation.Http | |||||||
|             base.Dispose(disposing); |             base.Dispose(disposing); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override Task ReceivedData(ReceivedDataEventArgs e) |  | ||||||
|         { |  | ||||||
|             if (e.RequestInfo is HttpResponse response) |  | ||||||
|             { |  | ||||||
|                 if (this.m_getContent) |  | ||||||
|                 { |  | ||||||
|                     response.TryGetContent(out _); |  | ||||||
|                 } |  | ||||||
|                 this.m_waitData.Set(response); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return base.ReceivedData(e); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -239,5 +340,42 @@ namespace ThingsGateway.Foundation.Http | |||||||
|             this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter()); |             this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter()); | ||||||
|             await base.OnConnecting(e); |             await base.OnConnecting(e); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         protected override async Task OnDisconnected(DisconnectEventArgs e) | ||||||
|  |         { | ||||||
|  |             this.m_waitData.Cancel(); | ||||||
|  |             this.m_waitDataAsync.Cancel(); | ||||||
|  |             await base.OnDisconnected(e); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         protected override Task ReceivedData(ReceivedDataEventArgs e) | ||||||
|  |         { | ||||||
|  |             if (e.RequestInfo is HttpResponse response) | ||||||
|  |             { | ||||||
|  |                 if (this.m_getContent) | ||||||
|  |                 { | ||||||
|  |                     response.TryGetContent(out _); | ||||||
|  |                 } | ||||||
|  |                 this.Set(response); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return base.ReceivedData(e); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void Reset(CancellationToken token) | ||||||
|  |         { | ||||||
|  |             this.m_waitData.Reset(); | ||||||
|  |             this.m_waitDataAsync.Reset(); | ||||||
|  |             this.m_waitData.SetCancellationToken(token); | ||||||
|  |             this.m_waitDataAsync.SetCancellationToken(token); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void Set(HttpResponse response) | ||||||
|  |         { | ||||||
|  |             this.m_waitData.Set(response); | ||||||
|  |             this.m_waitDataAsync.Set(response); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -0,0 +1,153 @@ | |||||||
|  | #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.Collections.Concurrent; | ||||||
|  |  | ||||||
|  | namespace ThingsGateway.Foundation.Http | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// HttpClient客户端连接池 | ||||||
|  |     /// </summary> | ||||||
|  |     public class HttpClientPool : SetupConfigObject | ||||||
|  |     { | ||||||
|  |         private readonly ConcurrentStack<HttpClient> m_httpClients = new ConcurrentStack<HttpClient>(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 最大连接数量。 | ||||||
|  |         /// </summary> | ||||||
|  |         public int MaxCount { get; set; } = 10; | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 目标地址 | ||||||
|  |         /// </summary> | ||||||
|  |         public IPHost RemoteIPHost { get; private set; } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 清除现有的所有链接 | ||||||
|  |         /// </summary> | ||||||
|  |         public void Clear() | ||||||
|  |         { | ||||||
|  |             while (this.m_httpClients.TryPop(out var client)) | ||||||
|  |             { | ||||||
|  |                 client.SafeDispose(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 发起请求,并获取数据体 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="request">请求体</param> | ||||||
|  |         /// <param name="timeout">等待超时时间</param> | ||||||
|  |         /// <param name="token">结束等待令箭</param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public HttpResponse RequestContent(HttpRequest request, int timeout = 10 * 1000, CancellationToken token = default) | ||||||
|  |         { | ||||||
|  |             var client = this.GetHttpClient(); | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 return client.RequestContent(request, false, timeout, token); | ||||||
|  |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 this.ReturnHttpClient(client); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 发起请求,并获取数据体 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="request">请求体</param> | ||||||
|  |         /// <param name="timeout">等待超时时间</param> | ||||||
|  |         /// <param name="token">结束等待令箭</param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public async Task<HttpResponse> RequestContentAsync(HttpRequest request, int timeout = 10000, CancellationToken token = default) | ||||||
|  |         { | ||||||
|  |             var client = await this.GetHttpClientAsync(); | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 return await client.RequestContentAsync(request, false, timeout, token); | ||||||
|  |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 this.ReturnHttpClient(client); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         protected override void Dispose(bool disposing) | ||||||
|  |         { | ||||||
|  |             this.Clear(); | ||||||
|  |             base.Dispose(disposing); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         protected override void LoadConfig(TouchSocketConfig config) | ||||||
|  |         { | ||||||
|  |             this.RemoteIPHost = config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty) ?? throw new ArgumentNullException(nameof(this.RemoteIPHost)); | ||||||
|  |             base.LoadConfig(config); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private HttpClient GetHttpClient() | ||||||
|  |         { | ||||||
|  |             this.ThrowIfDisposed(); | ||||||
|  |             HttpClient client; | ||||||
|  |             while (this.m_httpClients.TryPop(out client)) | ||||||
|  |             { | ||||||
|  |                 if (client.Online) | ||||||
|  |                 { | ||||||
|  |                     return client; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     client.SafeDispose(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             client = new HttpClient(); | ||||||
|  |             client.Setup(this.Config.Clone()); | ||||||
|  |             client.Connect(); | ||||||
|  |             return client; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private async Task<HttpClient> GetHttpClientAsync() | ||||||
|  |         { | ||||||
|  |             this.ThrowIfDisposed(); | ||||||
|  |             HttpClient client; | ||||||
|  |             while (this.m_httpClients.TryPop(out client)) | ||||||
|  |             { | ||||||
|  |                 if (client.Online) | ||||||
|  |                 { | ||||||
|  |                     return client; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     client.SafeDispose(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             client = new HttpClient(); | ||||||
|  |             client.Setup(this.Config.Clone()); | ||||||
|  |             await client.ConnectAsync(); | ||||||
|  |             return client; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void ReturnHttpClient(HttpClient client) | ||||||
|  |         { | ||||||
|  |             if (!client.Online || this.m_httpClients.Count >= 10) | ||||||
|  |             { | ||||||
|  |                 client.SafeDispose(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             this.m_httpClients.Push(client); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||