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" />
|
||||||
@@ -46,25 +47,44 @@
|
|||||||
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.HZW_QTJC_01\ThingsGateway.Foundation.Adapter.HZW_QTJC_01.csproj" />
|
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.HZW_QTJC_01\ThingsGateway.Foundation.Adapter.HZW_QTJC_01.csproj" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro' ">
|
||||||
|
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.LQTCP\Page\LQTCPDebugPage.razor.cs" Link="Pages\LQTCP\LQTCPDebugPage.razor.cs" />
|
||||||
|
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.LQTCP\Page\LQTCPDebugPage.razor" Link="Pages\LQTCP\LQTCPDebugPage.razor" />
|
||||||
|
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.LQTCP\ThingsGateway.Foundation.Adapter.LQTCP.csproj" />
|
||||||
|
|
||||||
|
|
||||||
|
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008DebugPage.razor.cs" Link="Pages\KELID2008\KELID2008DebugPage.razor.cs" />
|
||||||
|
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008OverTcpDebugPage.razor.cs" Link="Pages\KELID2008\KELID2008OverTcpDebugPage.razor.cs" />
|
||||||
|
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008DebugPage.razor" Link="Pages\KELID2008\KELID2008DebugPage.razor" />
|
||||||
|
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.KELID2008\Page\KELID2008OverTcpDebugPage.razor" Link="Pages\KELID2008\KELID2008OverTcpDebugPage.razor" />
|
||||||
|
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.KELID2008\ThingsGateway.Foundation.Adapter.KELID2008.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<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" />
|
||||||
|
|
||||||
|
|
||||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuDebugPage.razor.cs" />
|
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuDebugPage.razor.cs" />
|
||||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor" Link="Pages\Modbus\ModbusRtuDebugPage.razor" />
|
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor" Link="Pages\Modbus\ModbusRtuDebugPage.razor" />
|
||||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor.cs" />
|
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor.cs" />
|
||||||
@@ -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,25 +148,12 @@
|
|||||||
<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>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||