Compare commits

...

7 Commits

Author SHA1 Message Date
Kimdiego2098
517bd0394d update touchsocket 2023-10-13 19:16:12 +08:00
Kimdiego2098
70adb97fb5 update nuget 2023-10-13 16:14:42 +08:00
Kimdiego2098
623d44cabe update 3.0.0.7 2023-10-13 11:54:27 +08:00
Kimdiego2098
0d479ca00b 添加三菱mc 3e帧二进制通讯协议文档 2023-10-13 11:51:51 +08:00
Kimdiego2098
8bc49ef437 update demo 2023-10-12 18:52:44 +08:00
Kimdiego2098
f83fcec786 参数名称修改 2023-10-12 14:57:58 +08:00
Kimdiego2098
93690ce40d fix:mqtt保留消息未更新/更新错误 2023-10-12 14:57:36 +08:00
232 changed files with 18604 additions and 5902 deletions

View File

@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>3.0.0.6</Version> <Version>3.0.0.8</Version>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Authors>Diego</Authors> <Authors>Diego</Authors>

View File

@@ -144,6 +144,15 @@ public partial class MainLayout
var dataStringPro = var dataStringPro =
""" """
[ [
{
"Title": "Melsec",
"Children": [
{
"Href": "/QnA3E_Binary",
"Title": "QnA3E_Binary"
}
]
},
{ {
"Title": "ABCIP", "Title": "ABCIP",
"Children": [ "Children": [

View File

@@ -4,6 +4,14 @@
<DefineConstants>Pro</DefineConstants> <DefineConstants>Pro</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'"> <ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor.cs" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor.cs" />
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor" />
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Melsec\ThingsGateway.Foundation.Adapter.Melsec.csproj" />
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor.cs" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor.cs" /> <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" />

View File

@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>3.0.0.6</Version> <Version>3.0.0.8</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>
@@ -42,5 +42,9 @@
</None> </None>
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugSymbols>True</DebugSymbols>
<DebugType>Embedded</DebugType>
<EmbedAllSources>True</EmbedAllSources>
</PropertyGroup>
</Project> </Project>

View File

@@ -20,15 +20,12 @@ public class DLT645_2007Message : MessageBase, IMessage
public override int HeadBytesLength => -1; public override int HeadBytesLength => -1;
/// <inheritdoc/> /// <inheritdoc/>
public override bool CheckHeadBytes(byte[] head) public override bool CheckHeadBytes(byte[] heads)
{ {
BodyLength = -1; BodyLength = -1;
return true; return true;
} }
/// <inheritdoc/>
protected override void SendBytesThen()
{
}
} }

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
namespace ThingsGateway.Foundation.Adapter.DLT645; namespace ThingsGateway.Foundation.Adapter.DLT645;
internal static class PackHelper internal static class PackHelper

View File

@@ -1,442 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.DLT645</name>
</assembly>
<members>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DataInfo">
<summary>
解析参数
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.ByteLength">
<summary>
解析长度
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.Digtal">
<summary>
小数位
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.IsSigned">
<summary>
有符号解析
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDataInfos(System.Byte[])">
<summary>
获取返回的解析信息
</summary>
<param name="buffer"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDLT645_2007Command(System.String,System.Int32,System.Byte,System.String,System.Byte[],System.String[])">
<summary>
获取DLT645报文
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.#ctor(ThingsGateway.Foundation.Serial.SerialSession)">
<summary>
DLT645_2007
</summary>
<param name="serialSession"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.EnableFEHead">
<summary>
增加FE FE FE FE的报文头部
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.OperCode">
<summary>
写入需操作员代码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Password">
<summary>
写入密码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Station">
<summary>
通讯地址BCD码一般应该是12个字符
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.GetAddressDescription">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.SetDataAdapter">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
<summary>
广播校时
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
<summary>
冻结
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadDeviceStationAsync(System.Threading.CancellationToken)">
<summary>
读取通信地址
</summary>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
<summary>
修改波特率
</summary>
<param name="baudRate"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
<summary>
更新通信地址
</summary>
<param name="station"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
<summary>
修改密码
</summary>
<param name="level"></param>
<param name="oldPassword"></param>
<param name="newPassword"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.ControlCode">
<summary>
控制码
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Read">
<summary>
读数据
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadSub">
<summary>
读后续数据
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadStation">
<summary>
读站号
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Write">
<summary>
写数据
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteStation">
<summary>
写站号
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.BroadcastTime">
<summary>
广播校时
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Freeze">
<summary>
冻结
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteBaudRate">
<summary>
更新波特率
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WritePassword">
<summary>
更新密码
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address">
<summary>
DLT645_2007Address
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.UInt16)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.Byte[])">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.DataId">
<summary>
数据标识
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Reverse">
<summary>
反转解析
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Station">
<summary>
站号信息
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Parse(System.String,System.Int32)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ParseFrom(System.String,System.Int32)">
<summary>
解析地址
</summary>
<param name="address"></param>
<param name="length"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ToString">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.#ctor(ThingsGateway.Foundation.Core.EndianType)">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToDouble(System.Byte[],System.Int32)">
<summary>
DLT645协议转换double
</summary>
<param name="buffer">带数据项标识</param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[],System.Int32,System.Int32)">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter">
<summary>
DLT645_2007DataHandleAdapter
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.EnableFEHead">
<summary>
增加FE FE FE FE的报文头部
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.GetInstance">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp">
<summary>
DLT645_2007
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.#ctor(ThingsGateway.Foundation.Core.TcpClient)">
<summary>
DLT645_2007
</summary>
<param name="tcpClient"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.EnableFEHead">
<summary>
增加FE FE FE FE的报文头部
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.OperCode">
<summary>
写入需操作员代码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Password">
<summary>
写入密码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Station">
<summary>
通讯地址BCD码一般应该是12个字符
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.GetAddressDescription">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.SetDataAdapter">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
<summary>
广播校时
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
<summary>
冻结
</summary>
<param name="dateTime"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadDeviceStationAsync(System.Threading.CancellationToken)">
<summary>
读取通信地址
</summary>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
<summary>
修改波特率
</summary>
<param name="baudRate"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
<summary>
更新通信地址
</summary>
<param name="station"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
<summary>
修改密码
</summary>
<param name="level"></param>
<param name="oldPassword"></param>
<param name="newPassword"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.HeadBytesLength">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.CheckHeadBytes(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.SendBytesThen">
<inheritdoc/>
</member>
</members>
</doc>

View File

@@ -20,15 +20,12 @@ public class ModbusRtuMessage : MessageBase, IMessage
public override int HeadBytesLength => -1; public override int HeadBytesLength => -1;
/// <inheritdoc/> /// <inheritdoc/>
public override bool CheckHeadBytes(byte[] head) public override bool CheckHeadBytes(byte[] heads)
{ {
BodyLength = -1; BodyLength = -1;
return true; return true;
} }
/// <inheritdoc/>
protected override void SendBytesThen()
{
}
} }

View File

@@ -24,7 +24,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
/// <summary> /// <summary>
/// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端 /// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
/// </summary> /// </summary>
public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, OperResult> WriteData; public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, Task<OperResult>> WriteData;
/// <summary> /// <summary>
/// 继电器 /// 继电器
@@ -267,12 +267,13 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
{ {
return Task.FromResult(Write(address, value)); return Task.FromResult(Write(address, value));
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void Received(ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task Received(SerialSession client, ReceivedDataEventArgs e)
{ {
try try
{ {
var requestInfo = e.RequestInfo;
//接收外部报文 //接收外部报文
if (requestInfo is ModbusSerialServerMessage modbusServerMessage) if (requestInfo is ModbusSerialServerMessage modbusServerMessage)
{ {
@@ -312,7 +313,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
if (WriteData != null) if (WriteData != null)
{ {
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端 // 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess) if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
{ {
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length)); var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess) if (result.IsSuccess)
@@ -349,7 +350,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
if (WriteData != null) if (WriteData != null)
{ {
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess) if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
{ {
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData); var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess) if (result.IsSuccess)

View File

@@ -30,14 +30,11 @@ public class ModbusSerialServerMessage : MessageBase, IMessage
public override int HeadBytesLength => -1; public override int HeadBytesLength => -1;
/// <inheritdoc/> /// <inheritdoc/>
public override bool CheckHeadBytes(byte[] head) public override bool CheckHeadBytes(byte[] heads)
{ {
BodyLength = -1; BodyLength = -1;
return true; return true;
} }
/// <inheritdoc/>
protected override void SendBytesThen()
{
}
} }

View File

@@ -23,10 +23,10 @@ public class ModbusTcpMessage : MessageBase, IMessage
/// </summary> /// </summary>
public bool IsCheckMessageId { get; set; } = false; public bool IsCheckMessageId { get; set; } = false;
/// <inheritdoc/> /// <inheritdoc/>
public override bool CheckHeadBytes(byte[] head) public override bool CheckHeadBytes(byte[] heads)
{ {
if (head == null || head.Length <= 0) return false; if (heads == null || heads.Length <= 0) return false;
HeadBytes = head; HeadBytes = heads;
int num = (HeadBytes[4] * 256) + HeadBytes[5]; int num = (HeadBytes[4] * 256) + HeadBytes[5];
BodyLength = num; BodyLength = num;

View File

@@ -84,15 +84,6 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
return new OperResult<byte[]>(ex); return new OperResult<byte[]>(ex);
} }
} }
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
protected override void Connecting(SocketClient client, ConnectingEventArgs e)
{
Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
}
/// <inheritdoc/> /// <inheritdoc/>
public override void SetDataAdapter(object socketClient = null) public override void SetDataAdapter(object socketClient = null)
@@ -195,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.GetWaitingClientEx(new() { BreakTrigger = true }); var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true });
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken); var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo; return (MessageBase)result.RequestInfo;
} }
@@ -222,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.GetWaitingClientEx(new() { BreakTrigger = true }); var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true });
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken); var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
return (MessageBase)result.RequestInfo; return (MessageBase)result.RequestInfo;
} }

View File

@@ -25,7 +25,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
/// <summary> /// <summary>
/// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端 /// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
/// </summary> /// </summary>
public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, OperResult> WriteData; public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, Task<OperResult>> WriteData;
/// <summary> /// <summary>
/// 继电器 /// 继电器
@@ -284,12 +284,13 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
{ {
return Task.FromResult(Write(address, value)); return Task.FromResult(Write(address, value));
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void Received(SocketClient client, IRequestInfo requestInfo) protected override async Task Received(SocketClient client, ReceivedDataEventArgs e)
{ {
try try
{ {
var requestInfo = e.RequestInfo;
//接收外部报文 //接收外部报文
if (requestInfo is ModbusTcpServerMessage modbusServerMessage) if (requestInfo is ModbusTcpServerMessage modbusServerMessage)
{ {
@@ -330,7 +331,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
if (WriteData != null) if (WriteData != null)
{ {
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端 // 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess) if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
{ {
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length)); var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
if (result.IsSuccess) if (result.IsSuccess)
@@ -367,7 +368,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
if (WriteData != null) if (WriteData != null)
{ {
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess) if ((await WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
{ {
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData); var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
if (result.IsSuccess) if (result.IsSuccess)

View File

@@ -29,10 +29,10 @@ namespace ThingsGateway.Foundation.Adapter.Modbus
/// <inheritdoc/> /// <inheritdoc/>
public override int HeadBytesLength => 6; public override int HeadBytesLength => 6;
/// <inheritdoc/> /// <inheritdoc/>
public override bool CheckHeadBytes(byte[] head) public override bool CheckHeadBytes(byte[] heads)
{ {
if (head == null || head.Length != 6) return false; if (heads == null || heads.Length != 6) return false;
HeadBytes = head; HeadBytes = heads;
int num = (HeadBytes[4] * 256) + HeadBytes[5]; int num = (HeadBytes[4] * 256) + HeadBytes[5];
BodyLength = num; BodyLength = num;

View File

@@ -1,3 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
</PropertyGroup>
</Project> </Project>

View File

@@ -1,579 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.OPCDA</name>
</assembly>
<members>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
<summary>
移除符合条件的元素
</summary>
<typeparam name="T"></typeparam>
<param name="this"></param>
<param name="where"></param>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_SYSTEM_DEFAULT">
<summary>
The WIN32 system default locale.
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_USER_DEFAULT">
<summary>
The WIN32 user default locale.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.CreateInstance(System.Guid,System.String)">
<summary>
创建一个COM服务器的实例。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.GetSystemMessage(System.Int32)">
<summary>
指定错误消息文本检索系统。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.InitializeSecurity">
<summary>
初始化COM安全。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID)">
<summary>
从枚举器读取guid。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID)">
<summary>
从枚举器读取guid。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.RealseComServer(System.Object)">
<summary>
释放 COM 对象
</summary>
<param name="m_server"></param>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.Convert.FILETIME_BaseTime">
<summary>
windows的filetime是从1601-1-1 00:00:00开始的datetime是从1-1-1 00:00:00开始的
datetime和filetime的滴答单位都是100ns100纳秒千万分之一秒所以转换时只需要考虑开始时间即可
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnDataChangedHandler">
<summary>
值变化
</summary>
<param name="opcItems"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnReadCompletedHandler">
<summary>
读取
</summary>
<param name="opcItems"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnWriteCompletedHandler">
<summary>
写入
</summary>
<param name="opcItems"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult">
<summary>
返回结果
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Name">
<summary>
ID
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Quality">
<summary>
Quality
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.TimeStamp">
<summary>
TimeStamp
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Value">
<summary>
Value
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.InitIoInterfaces(System.Object)">
<summary>
建立连接
</summary>
<param name="handle"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.ReadAsync">
<summary>
组读取
</summary>
<exception cref="T:System.Runtime.InteropServices.ExternalException"></exception>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem">
<summary>
OpcItem
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.#ctor(System.String)">
<summary>
OpcItem
</summary>
<param name="itemId"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.AccessPath">
<summary>
AccessPath
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Blob">
<summary>
Blob
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.BlobSize">
<summary>
BlobSize
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ClientHandle">
<summary>
ClientHandle
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.IsActive">
<summary>
active(1) or not(0)
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ItemID">
<summary>
数据项在opc server的完全名称
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Quality">
<summary>
Quality
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.RunTimeDataType">
<summary>
RunTimeDataType
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ServerHandle">
<summary>
ServerHandle
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.TimeStamp">
<summary>
TimeStamp
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Value">
<summary>
Value
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.AddGroup(System.String,System.Boolean,System.Int32,System.Single)">
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.Browse(System.String)">
<summary>
获取节点
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.GetServerStatus">
<summary>
服务器状态
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus">
<summary>
ServerStatus
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.CurrentTime">
<summary>
CurrentTime
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.LastUpdateTime">
<summary>
LastUpdateTime
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.ServerState">
<summary>
ServerState
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.StartTime">
<summary>
StartTime
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.VendorInfo">
<summary>
VendorInfo
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.Version">
<summary>
Version
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery">
<summary>
OpcDiscovery
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery.GetOpcServer(System.String,System.String)">
<summary>
GetOpcServer
</summary>
<param name="serverName"></param>
<param name="host"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPoint">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPointContainer">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnectionPoints">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnections">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumString">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumUnknown">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCCommon">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCShutdown">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CONNECTDATA">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEDIRECTION">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEFILTER">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSETYPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCDATASOURCE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCENUMSCOPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCEUTYPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCNAMESPACETYPE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer10">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer20">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer30">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_XMLDAServer10">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumOPCItemAttributes">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO3">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowse">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowseServerAddressSpace">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCDataCallback">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemDeadbandMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemIO">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemProperties">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemSamplingMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCPublicGroupStateMgt">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServer">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerPublicGroups">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEELEMENT">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADER">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADERWRITE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMATTRIBUTES">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMDEF">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER1">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER2">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADERWRITE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTIES">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTY">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMRESULT">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMSTATE">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMVQT">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATUS">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Constants">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Qualities">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Properties">
<exclude />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.DataChangedEventHandler">
<summary>
订阅变化项
</summary>
<param name="values"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient">
<summary>
OPCDAClient
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ItemDicts">
<summary>
当前保存的需订阅列表
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.#ctor(ThingsGateway.Foundation.Core.ILog)">
<summary>
<inheritdoc/>
</summary>
<param name="logger"></param>
</member>
<member name="E:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.DataChangedHandler">
<summary>
数据变化事件
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.IsConnected">
<summary>
是否连接成功
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.OPCNode">
<summary>
当前配置
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItems(System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.List{ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem}})">
<summary>
添加节点,需要在连接成功后执行
</summary>
<param name="items">组名称/变量节点,注意每次添加的组名称不能相同</param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItemsWithSave(System.Collections.Generic.List{System.String})">
<summary>
设置节点并保存,每次重连会自动添加节点
</summary>
<param name="items"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Connect">
<summary>
连接服务器
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Disconnect">
<summary>
断开连接
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetBrowseElements(System.String)">
<summary>
浏览节点
</summary>
<param name="itemId"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetServerStatus">
<summary>
获取服务状态
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Init(ThingsGateway.Foundation.Adapter.OPCDA.OPCNode)">
<summary>
初始化设置
</summary>
<param name="node"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ReadItemsWithGroup(System.String)">
<summary>
按OPC组读取组内变量结果会在订阅事件中返回
</summary>
<param name="groupName">组名称值为null时读取全部组</param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.RemoveItems(System.Collections.Generic.List{System.String})">
<summary>
移除节点
</summary>
<param name="items"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken})">
<summary>
批量写入值
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode">
<summary>
OPCDA连接配置项
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ActiveSubscribe">
<summary>
是否订阅
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.CheckRate">
<summary>
内部检测重连间隔/min
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.DeadBand">
<summary>
死区
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.GroupSize">
<summary>
分组大小
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCIP">
<summary>
OPCIP
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCName">
<summary>
OPCNAME
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.UpdateRate">
<summary>
订阅间隔
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ToString">
<summary>
<inheritdoc/>
</summary>
<returns></returns>
</member>
</members>
</doc>

View File

@@ -1,468 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.OPCUA</name>
</assembly>
<members>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
<summary>
移除符合条件的元素
</summary>
<typeparam name="T"></typeparam>
<param name="this"></param>
<param name="where"></param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.SelectAsync``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Threading.Tasks.Task{``1}})">
<summary>
异步Select
</summary>
<typeparam name="T"></typeparam>
<typeparam name="TResult"></typeparam>
<param name="source"></param>
<param name="selector"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils">
<summary>
辅助类
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.Browse(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean)">
<summary>
Browses the address space and returns the references found.
</summary>
<param name="session">The session.</param>
<param name="nodesToBrowse">The set of browse operations to perform.</param>
<param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param>
<returns>
The references found. Null if an error occurred.
</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.PrepareBrowseNext(Opc.Ua.BrowseResultCollection)">
<summary>
Create the continuation point collection from the browse result
collection for the BrowseNext service.
</summary>
<param name="browseResultCollection">The browse result collection to use.</param>
<returns>The collection of continuation points for the BrowseNext service.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean,System.Threading.CancellationToken)">
<summary>
浏览地址空间
</summary>
<param name="session"></param>
<param name="nodesToBrowse"></param>
<param name="throwOnError"></param>
<param name="cancellationToken"></param>
<returns></returns>
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescription,System.Boolean,System.Threading.CancellationToken)">
<summary>
浏览地址空间
</summary>
<param name="session"></param>
<param name="nodeToBrowse"></param>
<param name="throwOnError"></param>
<param name="cancellationToken"></param>
<returns></returns>
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseSuperTypesAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,System.Boolean)">
<summary>
浏览地址空间并返回指定类型的所有节点
</summary>
<param name="session"></param>
<param name="typeId"></param>
<param name="throwOnError"></param>
<returns></returns>
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForInstanceAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
<summary>
Collects the fields for the instance.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForType(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
<summary>
Collects the fields for the type.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ConstructEventAsync(Opc.Ua.Client.ISession,Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList,System.Collections.Generic.Dictionary{Opc.Ua.NodeId,System.Type},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.NodeId})">
<summary>
Constructs an event object from a notification.
</summary>
<param name="session">The session.</param>
<param name="monitoredItem">The monitored item that produced the notification.</param>
<param name="notification">The notification.</param>
<param name="knownEventTypes">The known event types.</param>
<param name="eventTypeMappings">Mapping between event types and known event types.</param>
<returns>
The event object. Null if the notification is not a valid event type.
</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.DiscoverServers(Opc.Ua.ApplicationConfiguration)">
<summary>
Discovers the servers on the local machine.
</summary>
<param name="configuration">The configuration.</param>
<returns>A list of server urls.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.FindEventType(Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList)">
<summary>
Finds the type of the event for the notification.
</summary>
<param name="monitoredItem">The monitored item.</param>
<param name="notification">The notification.</param>
<returns>The NodeId of the EventType.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAttributeDisplayText(Opc.Ua.Client.ISession,System.UInt32,Opc.Ua.Variant)">
<summary>
指定的属性的显示文本。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.SelectEndpoint(System.String,System.Boolean)">
<summary>
Finds the endpoint that best matches the current settings.
</summary>
<param name="discoveryUrl">The discovery URL.</param>
<param name="useSecurity">if set to <c>true</c> select an endpoint that uses security.</param>
<returns>The best available endpoint.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.TranslateBrowsePaths(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.NamespaceTable,System.Threading.CancellationToken,System.String[])">
<summary>
返回一组相对路径的节点id
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection})">
<summary>
Collects the fields for the instance node.
</summary>
<param name="session">The session.</param>
<param name="nodeId">The node id.</param>
<param name="parentPath">The parent path.</param>
<param name="fields">The event fields.</param>
<param name="fieldNodeIds">The node id for the declaration of the field.</param>
<param name="foundNodes">The table of found nodes.</param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ContainsPath(Opc.Ua.SimpleAttributeOperandCollection,Opc.Ua.QualifiedNameCollection)">
<summary>
判断指定的select子句包含的浏览路径。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAccessLevelDisplayText(System.Byte)">
<summary>
访问级别属性的显示文本。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetEventNotifierDisplayText(System.Byte)">
<summary>
事件通知属性的显示文本
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils">
<summary>
扩展方法
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Decode(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
<summary>
解析获取DataValue
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecoderObject(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
<summary>
解析获取object
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecodeRawData(Opc.Ua.JsonDecoder,Opc.Ua.BuiltInType,System.Int32,System.String)">
<summary>
DecodeRawData
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Encode(Opc.Ua.IServiceMessageContext,Opc.Ua.BuiltInType,System.Object)">
<summary>
OPCUAValue解析为Jtoken
</summary>
<param name="Context"></param>
<param name="type"></param>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CreateEncoder(Opc.Ua.IServiceMessageContext,System.IO.Stream,System.Boolean,System.Boolean,System.Boolean,System.Boolean)">
<summary>
CreateEncoder
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CalculateActualValueRank(Newtonsoft.Json.Linq.JToken)">
<summary>
维度
</summary>
<param name="jToken"></param>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode">
<summary>
OPCUAClient配置项
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.OPCUrl">
<summary>
OPCUrl
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UserName">
<summary>
登录账号
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.Password">
<summary>
登录密码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.CheckDomain">
<summary>
检查域
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UpdateRate">
<summary>
更新间隔
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ActiveSubscribe">
<summary>
是否订阅
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.GroupSize">
<summary>
分组大小
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.DeadBand">
<summary>
死区
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.KeepAliveInterval">
<summary>
KeepAliveInterval/ms
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.IsUseSecurity">
<summary>
安全策略
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ToString">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.DataChangedEventHandler">
<summary>
订阅委托
</summary>
<param name="value"></param>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient">
<summary>
OPCUAClient
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCNode">
<summary>
当前配置
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ProductUri">
<summary>
ProductUri
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Variables">
<summary>
当前保存的变量名称列表
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient._variableDicts">
<summary>
当前的变量名称/OPC变量节点
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.dic_subscriptions">
<summary>
当前的订阅组,组名称/组
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReConnectHandler">
<summary>
SessionReconnectHandler
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.#ctor(ThingsGateway.Foundation.Core.ILog)">
<summary>
默认的构造函数实例化一个新的OPC UA类
</summary>
</member>
<member name="E:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.DataChangedHandler">
<summary>
订阅
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AppConfig">
<summary>
配置信息
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Connected">
<summary>
连接状态
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCUAName">
<summary>
OPCUAClient
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Session">
<summary>
当前活动会话。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AddSubscriptionAsync(System.String,System.String[])">
<summary>
新增订阅需要指定订阅组名称订阅的tag名数组
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveAllSubscription">
<summary>
移除所有的订阅消息
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveSubscription(System.String)">
<summary>
移除订阅消息
</summary>
<param name="subscriptionName">组名称</param>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.BrowseNodeReferenceAsync(System.String)">
<summary>
浏览一个节点的引用
</summary>
<param name="tag">节点值</param>
<returns>引用节点描述</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.CallMethodByNodeId(System.String,System.String,System.Object[])">
<summary>
调用服务器的方法
</summary>
<param name="tagParent">方法的父节点tag</param>
<param name="tag">方法的节点tag</param>
<param name="args">传递的参数</param>
<returns>输出的结果值</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadHistoryRawDataValues(System.String,System.DateTime,System.DateTime,System.UInt32,System.Boolean,System.Threading.CancellationToken)">
<summary>
读取历史数据
</summary>
<param name="tag">节点的索引</param>
<param name="start">开始时间</param>
<param name="end">结束时间</param>
<param name="count">读取的个数</param>
<param name="containBound">是否包含边界</param>
<param name="cancellationToken">cancellationToken</param>
<returns>读取的数据列表</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync">
<summary>
连接到服务器
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Disconnect">
<summary>
断开连接。
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync(System.String)">
<summary>
Creates a new session.
</summary>
<returns>The new session object.</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(System.String[],System.Threading.CancellationToken)">
<summary>
从服务器读取值
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
<summary>
异步写opc标签
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(Opc.Ua.NodeId[],System.Threading.CancellationToken)">
<summary>
从服务器读取值
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNodeAsync(System.String,System.Boolean,System.Threading.CancellationToken)">
<summary>
从服务器或缓存读取节点
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
<summary>
读取一个节点的所有属性
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.Collections.Generic.List{System.String},System.Threading.CancellationToken)">
<summary>
读取节点的所有属性
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributes(System.String)">
<summary>
读取一个节点的所有属性
</summary>
<param name="tag">节点信息</param>
<returns>节点的特性值</returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Dispose(System.Boolean)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Server_ReconnectComplete(System.Object,System.EventArgs)">
<summary>
连接处理器连接事件处理完成。
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute">
<summary>
读取属性过程中用于描述的
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Name">
<summary>
属性的名称
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.StatusCode">
<summary>
操作结果状态描述
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Type">
<summary>
属性的类型描述
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Value">
<summary>
属性的值,如果读取错误,返回文本描述
</summary>
</member>
</members>
</doc>

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
namespace ThingsGateway.Foundation.Adapter.Siemens; namespace ThingsGateway.Foundation.Adapter.Siemens;
/// <summary> /// <summary>

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #endregion
namespace ThingsGateway.Foundation.Adapter.Siemens; namespace ThingsGateway.Foundation.Adapter.Siemens;
internal static class PackHelper internal static class PackHelper

View File

@@ -67,7 +67,6 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
break; break;
} }
tcpClient.Connected += Connected;
} }
/// <summary> /// <summary>
@@ -293,8 +292,8 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
/// <inheritdoc/> /// <inheritdoc/>
public override void SetDataAdapter(object socketClient = null) public override void SetDataAdapter(object socketClient = null)
{ {
SiemensS7PLCDataHandleAdapter DataHandleAdapter = new(); SiemensS7PLCDataHandleAdapter dataHandleAdapter = new();
TcpClient.SetDataHandlingAdapter(DataHandleAdapter); TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
} }
@@ -476,17 +475,20 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
} }
#endregion #endregion
private void Connected(ITcpClient client, ConnectedEventArgs e) /// <inheritdoc/>
protected override async Task Connected(ITcpClient client, ConnectedEventArgs e)
{ {
try try
{ {
var result1 = SendThenResponse(ISO_CR); NormalDataHandlingAdapter dataHandleAdapter = new();
TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
var result1 = await SendThenResponseAsync(ISO_CR);
if (!result1.IsSuccess) if (!result1.IsSuccess)
{ {
Logger?.Warning($"{client.IP} : {client.Port}ISO_TP握手失败-{result1.Message}"); Logger?.Warning($"{client.IP} : {client.Port}ISO_TP握手失败-{result1.Message}");
return; return;
} }
var result2 = SendThenResponse(S7_PN); var result2 = await SendThenResponseAsync(S7_PN);
if (!result2.IsSuccess) if (!result2.IsSuccess)
{ {
Logger?.Warning($"{client.IP} : {client.Port}PDU初始化失败-{result2.Message}"); Logger?.Warning($"{client.IP} : {client.Port}PDU初始化失败-{result2.Message}");
@@ -499,7 +501,11 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
finally
{
SetDataAdapter();
}
await base.Connected(client, e);
} }
} }
} }

View File

@@ -1,336 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>ThingsGateway.Foundation.Adapter.Siemens</name>
</assembly>
<members>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.S7Area">
<summary>
区域
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.PE">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.PA">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.MK">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.DB">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.CT">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.TM">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.AI">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7Area.AQ">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress">
<summary>
西门子PLC地址数据信息
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.BitCode">
<summary>
bit位偏移
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.DataCode">
<summary>
数据块代码
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.DbBlock">
<summary>
DB块数据信息
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.GetAddressStart(System.String,System.Boolean)">
<summary>
获取起始地址
</summary>
<param name="address"></param>
<param name="isCounterOrTimer"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.GetBitCode(System.String)">
<summary>
获取bit
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ParseFrom(System.String)">
<summary>
解析地址
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ParseFrom(System.String,System.Int32)">
<summary>
解析地址
</summary>
<param name="address"></param>
<param name="length"></param>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.Parse(System.String,System.Int32)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensAddress.ToString">
<inheritdoc />
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.DateTime">
<summary>
https://github.com/S7NetPlus/s7netplus/blob/develop/S7.Net/Types/DateTime.cs
Contains the methods to convert between <see cref="T:System.DateTime"/> and S7 representation of datetime values.
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.DateTime.SpecMaximumDateTime">
<summary>
The maximum <see cref="T:System.DateTime"/> value supported by the specification.
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.DateTime.SpecMinimumDateTime">
<summary>
The minimum <see cref="T:System.DateTime"/> value supported by the specification.
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.FromByteArray(System.Byte[])">
<summary>
Parses a <see cref="T:System.DateTime"/> value from bytes.
</summary>
<param name="bytes">Input bytes read from PLC.</param>
<returns>A <see cref="T:System.DateTime"/> object representing the value read from PLC.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when the length of
<paramref name="bytes"/> is not 8 or any value in <paramref name="bytes"/>
is outside the valid range of values.</exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToArray(System.Byte[])">
<summary>
Parses an array of <see cref="T:System.DateTime"/> values from bytes.
</summary>
<param name="bytes">Input bytes read from PLC.</param>
<returns>An array of <see cref="T:System.DateTime"/> objects representing the values read from PLC.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when the length of
<paramref name="bytes"/> is not a multiple of 8 or any value in
<paramref name="bytes"/> is outside the valid range of values.</exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToByteArray(System.DateTime)">
<summary>
Converts a <see cref="T:System.DateTime"/> value to a byte array.
</summary>
<param name="dateTime">The DateTime value to convert.</param>
<returns>A byte array containing the S7 date time representation of <paramref name="dateTime"/>.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when the value of
<paramref name="dateTime"/> is before <see cref="P:SpecMinimumDateTime"/>
or after <see cref="P:SpecMaximumDateTime"/>.</exception>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.DateTime.ToByteArray(System.DateTime[])">
<summary>
Converts an array of <see cref="T:System.DateTime"/> values to a byte array.
</summary>
<param name="dateTimes">The DateTime values to convert.</param>
<returns>A byte array containing the S7 date time representations of <paramref name="dateTimes"/>.</returns>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown when any value of
<paramref name="dateTimes"/> is before <see cref="P:SpecMinimumDateTime"/>
or after <see cref="P:SpecMaximumDateTime"/>.</exception>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensHelper.S7_MULRW_HEADER">
<summary>
S7连读写请求头(包含ISO头和COTP头)
</summary>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Bit">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Byte">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Char">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Word">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Int">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.DWord">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.DInt">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Real">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Counter">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.S7WordLength.Timer">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage">
<inheritdoc/>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage.HeadBytesLength">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage.CheckHeadBytes(System.Byte[])">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S200">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S200Smart">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S300">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S400">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S1200">
<inheritdoc/>
</member>
<member name="F:ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum.S1500">
<inheritdoc/>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC">
<summary>
相关命令含义源自网络资料/Shrap7/s7netplus
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.#ctor(ThingsGateway.Foundation.Core.TcpClient,ThingsGateway.Foundation.Adapter.Siemens.SiemensEnum)">
<summary>
传入PLC类型程序内会改变相应PLC类型的S7协议LocalTSAP RemoteTSAP等
</summary>
<param name="tcpClient"></param>
<param name="siemensPLCEnum"></param>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.CurrentPlc">
<summary>
当前PLC类型
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.GetAddressDescription">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.GetBitOffset(System.String)">
<summary>
<inheritdoc/>
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.DestTSAP">
<summary>
远程TSAP需重新连接
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.LocalTSAP">
<summary>
本地TSAP需重新连接
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.PDULength">
<summary>
PDULength
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.Rack">
<summary>
机架号,需重新连接
</summary>
</member>
<member name="P:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.Slot">
<summary>
槽号,需重新连接
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateAsync(System.String,System.Threading.CancellationToken)">
<summary>
读取日期
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadDateTimeAsync(System.String,System.Threading.CancellationToken)">
<summary>
读取时间
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.ReadStringAsync(System.String,System.Text.Encoding,System.Threading.CancellationToken)">
<summary>
读取变长字符串
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.SetDataAdapter">
<summary>
<inheritdoc/>
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
<summary>
写入日期
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLC.WriteDateTimeAsync(System.String,System.DateTime,System.Threading.CancellationToken)">
<summary>
写入时间
</summary>
<returns></returns>
</member>
<member name="T:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter">
<summary>
SiemensS7PLCDataHandleAdapter
</summary>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.PackCommand(System.Byte[])">
<inheritdoc/>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.GetInstance">
<summary>
<inheritdoc/>
</summary>
<returns></returns>
</member>
<member name="M:ThingsGateway.Foundation.Adapter.Siemens.SiemensS7PLCDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Siemens.SiemensMessage,System.Byte[],System.Byte[],System.Byte[])">
<inheritdoc/>
</member>
</members>
</doc>

View File

@@ -24,7 +24,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
public ReadWriteDevicesSerialSessionBase(SerialSession serialSession) public ReadWriteDevicesSerialSessionBase(SerialSession serialSession)
{ {
SerialSession = serialSession; SerialSession = serialSession;
WaitingClientEx = SerialSession.GetWaitingClientEx(new() { BreakTrigger = true }); WaitingClientEx = SerialSession.GetWaitingClient(new() { ThrowBreakException = true });
SerialSession.Received -= Received; SerialSession.Received -= Received;
SerialSession.Connecting -= Connecting; SerialSession.Connecting -= Connecting;
SerialSession.Connected -= Connected; SerialSession.Connected -= Connected;
@@ -40,21 +40,15 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
/// <summary> /// <summary>
/// 接收解析 /// 接收解析
/// </summary> /// </summary>
protected virtual void Received(ByteBlock byteBlock, IRequestInfo requestInfo) /// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task Received(SerialSession client, ReceivedDataEventArgs e)
{ {
return EasyTask.CompletedTask;
}
}
private void Received(SerialSession client, ByteBlock byteBlock, IRequestInfo requestInfo)
{
try
{
Received(byteBlock, requestInfo);
}
catch (Exception ex)
{
Logger.Exception(this, ex);
}
}
/// <summary> /// <summary>
/// 串口管理对象 /// 串口管理对象
@@ -102,8 +96,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
{ {
try try
{ {
waitingOptions ??= new WaitingOptions { BreakTrigger = true, ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll }; waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = SerialSession.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); ResponsedData result = SerialSession.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data); return OperResult.CreateSuccessResult(result.Data);
} }
catch (Exception ex) catch (Exception ex)
@@ -117,8 +111,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
{ {
try try
{ {
waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll }; waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = await SerialSession.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); ResponsedData result = await SerialSession.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data); return OperResult.CreateSuccessResult(result.Data);
} }
catch (Exception ex) catch (Exception ex)
@@ -132,24 +126,34 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
{ {
return SerialSession.SerialProperty.ToString(); return SerialSession.SerialProperty.ToString();
} }
private void Connected(ISerialSession client, ConnectedEventArgs e) /// <summary>
/// Connected
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task Connected(ISerialSession client, ConnectedEventArgs e)
{ {
Logger?.Debug(client.SerialProperty.ToString() + "连接成功"); Logger?.Debug(client.SerialProperty.ToString() + "连接成功");
SetDataAdapter();
return EasyTask.CompletedTask;
} }
private void Connecting(ISerialSession client, SerialConnectingEventArgs e) private Task Connecting(ISerialSession client, SerialConnectingEventArgs e)
{ {
Logger?.Debug(client.SerialProperty.ToString() + "正在连接"); Logger?.Debug(client.SerialProperty.ToString() + "正在连接");
SetDataAdapter(); return EasyTask.CompletedTask;
} }
private void Disconnected(ISerialSessionBase client, DisconnectEventArgs e) private Task Disconnected(ISerialSessionBase client, DisconnectEventArgs e)
{ {
Logger?.Debug(client.SerialProperty.ToString() + "断开连接-" + e.Message); Logger?.Debug(client.SerialProperty.ToString() + "断开连接-" + e.Message);
return EasyTask.CompletedTask;
} }
private void Disconnecting(ISerialSessionBase client, DisconnectEventArgs e) private Task Disconnecting(ISerialSessionBase client, DisconnectEventArgs e)
{ {
Logger?.Debug(client.SerialProperty.ToString() + "正在主动断开连接-" + e.Message); Logger?.Debug(client.SerialProperty.ToString() + "正在主动断开连接-" + e.Message);
return EasyTask.CompletedTask;
} }
} }

View File

@@ -23,7 +23,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
public ReadWriteDevicesTcpClientBase(TcpClient tcpClient) public ReadWriteDevicesTcpClientBase(TcpClient tcpClient)
{ {
TcpClient = tcpClient; TcpClient = tcpClient;
WaitingClientEx = TcpClient.GetWaitingClientEx(new() { BreakTrigger = true }); WaitingClientEx = TcpClient.GetWaitingClient(new() { ThrowBreakException = true });
TcpClient.Connecting -= Connecting; TcpClient.Connecting -= Connecting;
TcpClient.Connected -= Connected; TcpClient.Connected -= Connected;
TcpClient.Disconnecting -= Disconnecting; TcpClient.Disconnecting -= Disconnecting;
@@ -59,7 +59,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
/// <inheritdoc/> /// <inheritdoc/>
public override Task ConnectAsync(CancellationToken cancellationToken) public override Task ConnectAsync(CancellationToken cancellationToken)
{ {
return TcpClient.ConnectAsync(ConnectTimeOut); return TcpClient.ConnectAsync(ConnectTimeOut, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -86,8 +86,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
{ {
try try
{ {
waitingOptions ??= new WaitingOptions { BreakTrigger = true, ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll }; waitingOptions ??= new WaitingOptions { ThrowBreakException = true, };
ResponsedData result = TcpClient.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); ResponsedData result = TcpClient.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data); return OperResult.CreateSuccessResult(result.Data);
} }
catch (Exception ex) catch (Exception ex)
@@ -101,8 +101,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
{ {
try try
{ {
waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll }; waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = await TcpClient.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); ResponsedData result = await TcpClient.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data); return OperResult.CreateSuccessResult(result.Data);
} }
catch (Exception ex) catch (Exception ex)
@@ -116,24 +116,34 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
{ {
return TcpClient.RemoteIPHost.ToString(); return TcpClient.RemoteIPHost.ToString();
} }
private void Connected(ITcpClient client, ConnectedEventArgs e) /// <summary>
/// Connected
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task Connected(ITcpClient client, ConnectedEventArgs e)
{ {
Logger?.Debug(client.RemoteIPHost.ToString() + "连接成功"); Logger?.Debug(client.RemoteIPHost.ToString() + "连接成功");
SetDataAdapter();
return EasyTask.CompletedTask;
} }
private void Connecting(ITcpClient client, ConnectingEventArgs e) private Task Connecting(ITcpClient client, ConnectingEventArgs e)
{ {
Logger?.Debug(client.RemoteIPHost.ToString() + "正在连接"); Logger?.Debug(client.RemoteIPHost.ToString() + "正在连接");
SetDataAdapter(); return EasyTask.CompletedTask;
} }
private void Disconnected(ITcpClientBase client, DisconnectEventArgs e) private Task Disconnected(ITcpClientBase client, DisconnectEventArgs e)
{ {
Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message); Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message);
return EasyTask.CompletedTask;
} }
private void Disconnecting(ITcpClientBase client, DisconnectEventArgs e) private Task Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
{ {
Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message); Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message);
return EasyTask.CompletedTask;
} }
} }

View File

@@ -77,57 +77,54 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
if (CascadeDisposal) if (CascadeDisposal)
TcpService.SafeDispose(); TcpService.SafeDispose();
} }
/// <summary>
/// 接收解析
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual Task Received(SocketClient client, ReceivedDataEventArgs e)
{
return EasyTask.CompletedTask;
}
/// <inheritdoc/> /// <inheritdoc/>
public override string ToString() public override string ToString()
{ {
return TcpService.ServerName; return TcpService.ServerName;
} }
/// <summary>
/// 接收解析
/// </summary>
protected virtual void Received(SocketClient client, IRequestInfo requestInfo)
{
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void Connected(SocketClient client, ConnectedEventArgs e) protected virtual Task Connected(SocketClient client, ConnectedEventArgs e)
{ {
Logger?.Debug(client.IP + ":" + client.Port + "连接成功"); Logger?.Debug(client.IP + ":" + client.Port + "连接成功");
return EasyTask.CompletedTask;
} }
/// <inheritdoc/> /// <inheritdoc/>
protected virtual void Connecting(SocketClient client, ConnectingEventArgs e) protected virtual Task Connecting(SocketClient client, ConnectingEventArgs e)
{ {
Logger?.Debug(client.IP + ":" + client.Port + "正在连接"); Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
SetDataAdapter(client); SetDataAdapter(client);
return EasyTask.CompletedTask;
} }
/// <inheritdoc/> /// <inheritdoc/>
protected virtual void Disconnected(ITcpClientBase client, DisconnectEventArgs e) protected virtual Task Disconnected(ITcpClientBase client, DisconnectEventArgs e)
{ {
Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message); Logger?.Debug(client.IP + ":" + client.Port + "断开连接-" + e.Message);
return EasyTask.CompletedTask;
} }
/// <inheritdoc/> /// <inheritdoc/>
protected virtual void Disconnecting(ITcpClientBase client, DisconnectEventArgs e) protected virtual Task Disconnecting(ITcpClientBase client, DisconnectEventArgs e)
{ {
Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message); Logger?.Debug(client.IP + ":" + client.Port + "正在主动断开连接-" + e.Message);
return EasyTask.CompletedTask;
} }
private void Received(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
{
try
{
Received(client, requestInfo);
}
catch (Exception ex)
{
Logger.Exception(this, ex);
}
}
} }

View File

@@ -22,7 +22,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
{ {
UdpSession = udpSession; UdpSession = udpSession;
SetDataAdapter(); SetDataAdapter();
WaitingClientEx = UdpSession.GetWaitingClientEx(new() { BreakTrigger = true }); WaitingClientEx = UdpSession.GetWaitingClient(new() { ThrowBreakException = true });
} }
/// <summary> /// <summary>
@@ -64,8 +64,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
{ {
try try
{ {
waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll }; waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = UdpSession.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken); ResponsedData result = UdpSession.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data); return OperResult.CreateSuccessResult(result.Data);
} }
catch (Exception ex) catch (Exception ex)
@@ -79,8 +79,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
{ {
try try
{ {
waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll }; waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
ResponsedData result = await UdpSession.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken); ResponsedData result = await UdpSession.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
return OperResult.CreateSuccessResult(result.Data); return OperResult.CreateSuccessResult(result.Data);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -143,6 +143,21 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
GoSend(bytes, 0, bytes.Length); GoSend(bytes, 0, bytes.Length);
Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}"); Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}");
} }
/// <summary>
/// 发送方法,会重新建立<see cref="Request"/>
/// </summary>
protected async Task GoSendAsync(byte[] item)
{
byte[] bytes;
if (IsSendPackCommand)
bytes = PackCommand(item);
else
bytes = item;
Request = GetInstance();
Request.SendBytes = bytes;
await GoSendAsync(bytes, 0, bytes.Length);
Logger?.Trace($"{FoundationConst.LogMessageHeader}{ToString()}- 发送:{Request.SendBytes.ToHexString(' ')}");
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void PreviewSend(byte[] buffer, int offset, int length) protected override void PreviewSend(byte[] buffer, int offset, int length)
@@ -150,6 +165,12 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
GoSend(buffer); GoSend(buffer);
} }
/// <inheritdoc/>
protected override Task PreviewSendAsync(byte[] buffer, int offset, int length)
{
return GoSendAsync(buffer);
}
/// <summary> /// <summary>
/// 报文拆包 /// 报文拆包
/// </summary> /// </summary>

View File

@@ -128,11 +128,6 @@ public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHa
{ {
throw new System.NotImplementedException();//因为设置了不支持拼接发送,所以该方法可以不实现。 throw new System.NotImplementedException();//因为设置了不支持拼接发送,所以该方法可以不实现。
} }
/// <inheritdoc/>
protected override void PreviewSend(IRequestInfo requestInfo)
{
throw new System.NotImplementedException();//因为设置了不支持,所以该方法可以不实现。
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void Reset() protected override void Reset()

View File

@@ -43,7 +43,7 @@ public abstract class MessageBase : OperResult<byte[]>, IMessage
} }
/// <inheritdoc/> /// <inheritdoc/>
public abstract bool CheckHeadBytes(byte[] head); public abstract bool CheckHeadBytes(byte[] heads);
/// <summary> /// <summary>
/// 写入<see cref="SendBytes"/>后触发此方法 /// 写入<see cref="SendBytes"/>后触发此方法

View File

@@ -51,7 +51,7 @@ public interface IMessage : IOperResult, IRequestInfo
/// <summary> /// <summary>
/// 检查头子节的合法性,并赋值<see cref="BodyLength"/><br /> /// 检查头子节的合法性,并赋值<see cref="BodyLength"/><br />
/// </summary> /// </summary>
/// <param name="head">接收的头子节</param> /// <param name="heads">接收的头子节</param>
/// <returns>是否成功的结果</returns> /// <returns>是否成功的结果</returns>
bool CheckHeadBytes(byte[] head); bool CheckHeadBytes(byte[] heads);
} }

View File

@@ -19,5 +19,20 @@
<PackageReference Include="System.IO.Ports" Version="7.0.0" /> <PackageReference Include="System.IO.Ports" Version="7.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\favicon-16x16.png" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\favicon-32x32.png" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\index.html" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\oauth2-redirect.html" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\openapi.json" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-bundle.js" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-es-bundle-core.js" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-es-bundle.js" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui-standalone-preset.js" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui.css" />
<EmbeddedResource Include="TouchSocket\WebApi.Swagger\api\swagger-ui.js" />
</ItemGroup>
</Project> </Project>

View File

@@ -30,7 +30,7 @@ namespace ThingsGateway.Foundation.Core
/// 具有释放的对象。 /// 具有释放的对象。
/// 并未实现析构函数相关。 /// 并未实现析构函数相关。
/// </summary> /// </summary>
public class DisposableObject : IDisposable public partial class DisposableObject : IDisposable
{ {
/// <summary> /// <summary>
/// 判断是否已释放。 /// 判断是否已释放。

View File

@@ -69,14 +69,6 @@ namespace ThingsGateway.Foundation.Core
this.Owner = owner; this.Owner = owner;
} }
/// <summary>
/// 发送数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="requestInfo"></param>
public void SendInput(IRequestInfo requestInfo)
{
this.PreviewSend(requestInfo);
}
/// <summary> /// <summary>
/// 在解析时发生错误。 /// 在解析时发生错误。
@@ -96,11 +88,6 @@ namespace ThingsGateway.Foundation.Core
} }
} }
/// <summary>
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="requestInfo"></param>
protected abstract void PreviewSend(IRequestInfo requestInfo);
/// <summary> /// <summary>
/// 重置解析器到初始状态,一般在<see cref="OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。 /// 重置解析器到初始状态,一般在<see cref="OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。

View File

@@ -78,6 +78,24 @@ namespace ThingsGateway.Foundation.Core
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
/// <inheritdoc/>
protected override Task PreviewSendAsync(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
protected override Task PreviewSendAsync(byte[] buffer, int offset, int length)
{
return this.GoSendAsync(buffer, offset, length);
}
/// <inheritdoc/>
protected override Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
{
throw new NotImplementedException();
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>

View File

@@ -242,6 +242,131 @@ namespace ThingsGateway.Foundation.Core
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <inheritdoc/>
protected override Task PreviewSendAsync(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
protected override async Task PreviewSendAsync(byte[] buffer, int offset, int length)
{
if (length < this.MinPackageSize)
{
throw new Exception("发送数据小于设定值,相同解析器可能无法收到有效数据,已终止发送");
}
if (length > this.MaxPackageSize)
{
throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
}
ByteBlock byteBlock = null;
byte[] lenBytes = null;
switch (this.FixedHeaderType)
{
case FixedHeaderType.Byte:
{
var dataLen = (byte)(length - offset);
byteBlock = new ByteBlock(dataLen + 1);
lenBytes = new byte[] { dataLen };
break;
}
case FixedHeaderType.Ushort:
{
var dataLen = (ushort)(length - offset);
byteBlock = new ByteBlock(dataLen + 2);
lenBytes = TouchSocketBitConverter.Default.GetBytes(dataLen);
break;
}
case FixedHeaderType.Int:
{
var dataLen = length - offset;
byteBlock = new ByteBlock(dataLen + 4);
lenBytes = TouchSocketBitConverter.Default.GetBytes(dataLen);
break;
}
}
try
{
byteBlock.Write(lenBytes);
byteBlock.Write(buffer, offset, length);
await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
finally
{
byteBlock.Dispose();
}
}
/// <inheritdoc/>
protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
{
if (transferBytes.Count == 0)
{
return;
}
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
if (length < this.MinPackageSize)
{
throw new Exception("发送数据小于设定值,相同解析器可能无法收到有效数据,已终止发送");
}
if (length > this.MaxPackageSize)
{
throw new Exception("发送数据大于设定值,相同解析器可能无法收到有效数据,已终止发送");
}
ByteBlock byteBlock = null;
byte[] lenBytes = null;
switch (this.FixedHeaderType)
{
case FixedHeaderType.Byte:
{
var dataLen = (byte)length;
byteBlock = new ByteBlock(dataLen + 1);
lenBytes = new byte[] { dataLen };
break;
}
case FixedHeaderType.Ushort:
{
var dataLen = (ushort)length;
byteBlock = new ByteBlock(dataLen + 2);
lenBytes = TouchSocketBitConverter.Default.GetBytes(dataLen);
break;
}
case FixedHeaderType.Int:
{
byteBlock = new ByteBlock(length + 4);
lenBytes = TouchSocketBitConverter.Default.GetBytes(length);
break;
}
}
try
{
byteBlock.Write(lenBytes);
foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
finally
{
byteBlock.Dispose();
}
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>

View File

@@ -183,6 +183,70 @@ namespace ThingsGateway.Foundation.Core
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <inheritdoc/>
protected override Task PreviewSendAsync(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
protected override async Task PreviewSendAsync(byte[] buffer, int offset, int length)
{
var dataLen = length - offset;
if (dataLen > this.FixedSize)
{
throw new OverlengthException("发送的数据包长度大于FixedSize");
}
var byteBlock = new ByteBlock(this.FixedSize);
byteBlock.Write(buffer, offset, length);
for (var i = byteBlock.Pos; i < this.FixedSize; i++)
{
byteBlock.Buffer[i] = 0;
}
byteBlock.SetLength(this.FixedSize);
try
{
await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
finally
{
byteBlock.Dispose();
}
}
/// <inheritdoc/>
protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
{
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
if (length > this.FixedSize)
{
throw new OverlengthException("发送的数据包长度大于FixedSize");
}
var byteBlock = new ByteBlock(this.FixedSize);
foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
Array.Clear(byteBlock.Buffer, byteBlock.Pos, this.FixedSize);
byteBlock.SetLength(this.FixedSize);
try
{
await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
finally
{
byteBlock.Dispose();
}
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>

View File

@@ -240,5 +240,64 @@ namespace ThingsGateway.Foundation.Core
byteBlock.Dispose(); byteBlock.Dispose();
} }
} }
/// <inheritdoc/>
protected override Task PreviewSendAsync(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
protected override async Task PreviewSendAsync(byte[] buffer, int offset, int length)
{
if (length > this.MaxPackageSize)
{
throw new Exception("发送的数据长度大于适配器设定的最大值,接收方可能会抛弃。");
}
var dataLen = length - offset + this.m_terminatorCode.Length;
var byteBlock = new ByteBlock(dataLen);
byteBlock.Write(buffer, offset, length);
byteBlock.Write(this.m_terminatorCode);
try
{
await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
finally
{
byteBlock.Dispose();
}
}
/// <inheritdoc/>
protected override async Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
{
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
if (length > this.MaxPackageSize)
{
throw new Exception("发送的数据长度大于适配器设定的最大值,接收方可能会抛弃。");
}
var dataLen = length + this.m_terminatorCode.Length;
var byteBlock = new ByteBlock(dataLen);
foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
byteBlock.Write(this.m_terminatorCode);
try
{
await this.GoSendAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
finally
{
byteBlock.Dispose();
}
}
} }
} }

View File

@@ -10,6 +10,19 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endregion #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 namespace ThingsGateway.Foundation.Core
{ {
/// <summary> /// <summary>
@@ -37,4 +50,4 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
public bool? UpdateCacheTimeWhenRev { get; set; } public bool? UpdateCacheTimeWhenRev { get; set; }
} }
} }

View File

@@ -36,9 +36,9 @@ namespace ThingsGateway.Foundation.Core
public TimeSpan CacheTimeout { get; set; } = TimeSpan.FromSeconds(1); public TimeSpan CacheTimeout { get; set; } = TimeSpan.FromSeconds(1);
/// <summary> /// <summary>
/// 是否启用缓存超时。默认true。 /// 是否启用缓存超时。默认false。
/// </summary> /// </summary>
public bool CacheTimeoutEnable { get; set; } = true; public bool CacheTimeoutEnable { get; set; } = false;
/// <summary> /// <summary>
/// 当接收数据处理完成后,回调该函数执行接收 /// 当接收数据处理完成后,回调该函数执行接收
@@ -46,10 +46,15 @@ namespace ThingsGateway.Foundation.Core
public Action<ByteBlock, IRequestInfo> ReceivedCallBack { get; set; } public Action<ByteBlock, IRequestInfo> ReceivedCallBack { get; set; }
/// <summary> /// <summary>
/// 当接收数据处理完成后,回调该函数执行发送 /// 当发送数据处理完成后,回调该函数执行发送
/// </summary> /// </summary>
public Action<byte[], int, int> SendCallBack { get; set; } public Action<byte[], int, int> SendCallBack { get; set; }
/// <summary>
/// 当发送数据处理完成后,回调该函数执行异步发送
/// </summary>
public Func<byte[], int, int, Task> SendAsyncCallBack { get; set; }
/// <summary> /// <summary>
/// 是否在收到数据时即刷新缓存时间。默认true。 /// 是否在收到数据时即刷新缓存时间。默认true。
/// <list type="number"> /// <list type="number">
@@ -64,6 +69,12 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
protected DateTime LastCacheTime { get; set; } protected DateTime LastCacheTime { get; set; }
/// <inheritdoc/>
public override bool CanSendRequestInfo => false;
/// <inheritdoc/>
public override bool CanSplicingSend => false;
/// <summary> /// <summary>
/// 收到数据的切入点,该方法由框架自动调用。 /// 收到数据的切入点,该方法由框架自动调用。
/// </summary> /// </summary>
@@ -80,6 +91,17 @@ namespace ThingsGateway.Foundation.Core
} }
} }
#region SendInput
/// <summary>
/// 发送数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="requestInfo"></param>
public void SendInput(IRequestInfo requestInfo)
{
this.PreviewSend(requestInfo);
}
/// <summary> /// <summary>
/// 发送数据的切入点,该方法由框架自动调用。 /// 发送数据的切入点,该方法由框架自动调用。
/// </summary> /// </summary>
@@ -100,6 +122,98 @@ namespace ThingsGateway.Foundation.Core
this.PreviewSend(transferBytes); this.PreviewSend(transferBytes);
} }
/// <summary>
/// 发送数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="requestInfo"></param>
/// <returns></returns>
public Task SendInputAsync(IRequestInfo requestInfo)
{
return this.PreviewSendAsync(requestInfo);
}
/// <summary>
/// 发送数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public Task SendInputAsync(byte[] buffer, int offset, int length)
{
return this.PreviewSendAsync(buffer, offset, length);
}
/// <summary>
/// 发送数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="transferBytes"></param>
public Task SendInputAsync(IList<ArraySegment<byte>> transferBytes)
{
return this.PreviewSendAsync(transferBytes);
}
/// <summary>
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="requestInfo"></param>
protected virtual void PreviewSend(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <summary>
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="buffer">数据</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
protected virtual void PreviewSend(byte[] buffer, int offset, int length)
{
this.GoSend(buffer, offset, length);
}
/// <summary>
/// 组合发送预处理数据,
/// 当属性SplicingSend实现为True时系统才会调用该方法。
/// </summary>
/// <param name="transferBytes">代发送数据组合</param>
protected virtual void PreviewSend(IList<ArraySegment<byte>> transferBytes)
{
throw new NotImplementedException();
}
/// <summary>
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="requestInfo"></param>
protected virtual Task PreviewSendAsync(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <summary>
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="buffer">数据</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
protected virtual Task PreviewSendAsync(byte[] buffer, int offset, int length)
{
return this.GoSendAsync(buffer, offset, length);
}
/// <summary>
/// 组合发送预处理数据,
/// 当属性SplicingSend实现为True时系统才会调用该方法。
/// </summary>
/// <param name="transferBytes">代发送数据组合</param>
protected virtual Task PreviewSendAsync(IList<ArraySegment<byte>> transferBytes)
{
throw new NotImplementedException();
}
#endregion SendInput
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
@@ -130,27 +244,24 @@ namespace ThingsGateway.Foundation.Core
this.SendCallBack.Invoke(buffer, offset, length); this.SendCallBack.Invoke(buffer, offset, length);
} }
/// <summary>
/// 异步发送已经经过预先处理后的数据
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
protected Task GoSendAsync(byte[] buffer, int offset, int length)
{
return this.SendAsyncCallBack.Invoke(buffer, offset, length);
}
/// <summary> /// <summary>
/// 当接收到数据后预先处理数据,然后调用<see cref="GoReceived(ByteBlock, IRequestInfo)"/>处理数据 /// 当接收到数据后预先处理数据,然后调用<see cref="GoReceived(ByteBlock, IRequestInfo)"/>处理数据
/// </summary> /// </summary>
/// <param name="byteBlock"></param> /// <param name="byteBlock"></param>
protected abstract void PreviewReceived(ByteBlock byteBlock); protected abstract void PreviewReceived(ByteBlock byteBlock);
/// <summary>
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="buffer">数据</param>
/// <param name="offset">偏移</param>
/// <param name="length">长度</param>
protected abstract void PreviewSend(byte[] buffer, int offset, int length);
/// <summary>
/// 组合发送预处理数据,
/// 当属性SplicingSend实现为True时系统才会调用该方法。
/// </summary>
/// <param name="transferBytes">代发送数据组合</param>
protected abstract void PreviewSend(IList<ArraySegment<byte>> transferBytes);
/// <summary> /// <summary>
/// 重置解析器到初始状态,一般在<see cref="DataHandlingAdapter.OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。 /// 重置解析器到初始状态,一般在<see cref="DataHandlingAdapter.OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。
/// </summary> /// </summary>

View File

@@ -63,9 +63,11 @@ namespace ThingsGateway.Foundation.Core
/// <returns></returns> /// <returns></returns>
public static SingleStreamDataAdapterTester CreateTester(SingleStreamDataHandlingAdapter adapter, int bufferLength = 1024, Action<ByteBlock, IRequestInfo> receivedCallBack = default) public static SingleStreamDataAdapterTester CreateTester(SingleStreamDataHandlingAdapter adapter, int bufferLength = 1024, Action<ByteBlock, IRequestInfo> receivedCallBack = default)
{ {
var tester = new SingleStreamDataAdapterTester(); var tester = new SingleStreamDataAdapterTester
tester.m_adapter = adapter; {
tester.m_bufferLength = bufferLength; m_adapter = adapter,
m_bufferLength = bufferLength
};
adapter.SendCallBack = tester.SendCallback; adapter.SendCallBack = tester.SendCallback;
adapter.ReceivedCallBack = tester.OnReceived; adapter.ReceivedCallBack = tester.OnReceived;
tester.m_receivedCallBack = receivedCallBack; tester.m_receivedCallBack = receivedCallBack;
@@ -129,7 +131,7 @@ namespace ThingsGateway.Foundation.Core
{ {
while (!this.m_dispose) while (!this.m_dispose)
{ {
if (this.tryGet(out var byteBlocks)) if (this.TryGet(out var byteBlocks))
{ {
foreach (var block in byteBlocks) foreach (var block in byteBlocks)
{ {
@@ -163,7 +165,7 @@ namespace ThingsGateway.Foundation.Core
this.m_asyncBytes.Enqueue(asyncByte); this.m_asyncBytes.Enqueue(asyncByte);
} }
private bool tryGet(out List<ByteBlock> byteBlocks) private bool TryGet(out List<ByteBlock> byteBlocks)
{ {
byteBlocks = new List<ByteBlock>(); byteBlocks = new List<ByteBlock>();
ByteBlock block = null; ByteBlock block = null;

View File

@@ -70,10 +70,9 @@ namespace ThingsGateway.Foundation.Core
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="fromType"></param> /// <param name="fromType"></param>
/// <param name="ps"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
public object Resolve(Type fromType, object[] ps = null, string key = "") public object Resolve(Type fromType, string key = "")
{ {
if (fromType == typeof(IContainer)) if (fromType == typeof(IContainer))
{ {
@@ -108,11 +107,11 @@ namespace ThingsGateway.Foundation.Core
{ {
if (descriptor.ToType.IsGenericType) if (descriptor.ToType.IsGenericType)
{ {
return (descriptor.ToInstance = this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps)); return (descriptor.ToInstance = this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments())));
} }
else else
{ {
return (descriptor.ToInstance = this.Create(descriptor, descriptor.ToType, ps)); return descriptor.ToInstance = this.Create(descriptor, descriptor.ToType);
} }
} }
} }
@@ -120,11 +119,11 @@ namespace ThingsGateway.Foundation.Core
if (descriptor.ToType.IsGenericType) if (descriptor.ToType.IsGenericType)
{ {
return this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps); return this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()));
} }
else else
{ {
return this.Create(descriptor, descriptor.ToType, ps); return this.Create(descriptor, descriptor.ToType);
} }
} }
} }
@@ -143,10 +142,10 @@ namespace ThingsGateway.Foundation.Core
} }
lock (descriptor) lock (descriptor)
{ {
return descriptor.ToInstance ??= this.Create(descriptor, descriptor.ToType, ps); return descriptor.ToInstance ??= this.Create(descriptor, descriptor.ToType);
} }
} }
return this.Create(descriptor, descriptor.ToType, ps); return this.Create(descriptor, descriptor.ToType);
} }
else else
{ {
@@ -172,7 +171,7 @@ namespace ThingsGateway.Foundation.Core
this.m_registrations.TryRemove(k, out _); this.m_registrations.TryRemove(k, out _);
} }
private object Create(DependencyDescriptor descriptor, Type toType, object[] ops) private object Create(DependencyDescriptor descriptor, Type toType)
{ {
var ctor = toType.GetConstructors().FirstOrDefault(x => x.IsDefined(typeof(DependencyInjectAttribute), true)); var ctor = toType.GetConstructors().FirstOrDefault(x => x.IsDefined(typeof(DependencyInjectAttribute), true));
if (ctor is null) if (ctor is null)
@@ -198,28 +197,21 @@ namespace ThingsGateway.Foundation.Core
{ {
for (var i = 0; i < parameters.Length; i++) for (var i = 0; i < parameters.Length; i++)
{ {
if (ops != null && ops.Length - 1 >= i) if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
{ {
ps[i] = ops[i]; ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
} }
else else
{ {
if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string)) if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
{ {
ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default; var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? parameters[i].ParameterType;
ps[i] = this.Resolve(type, attribute.Key);
} }
else else
{ {
if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true)) ps[i] = this.Resolve(parameters[i].ParameterType, null);
{
var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? parameters[i].ParameterType;
ps[i] = this.Resolve(type, default, attribute.Key);
}
else
{
ps[i] = this.Resolve(parameters[i].ParameterType, null);
}
} }
} }
} }
@@ -239,7 +231,7 @@ namespace ThingsGateway.Foundation.Core
{ {
var attribute = item.GetCustomAttribute<DependencyInjectAttribute>(); var attribute = item.GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? item.PropertyType; var type = attribute.Type ?? item.PropertyType;
obj = this.Resolve(type, default, attribute.Key); obj = this.Resolve(type, attribute.Key);
} }
else else
{ {
@@ -259,28 +251,21 @@ namespace ThingsGateway.Foundation.Core
ps = new object[parameters.Length]; ps = new object[parameters.Length];
for (var i = 0; i < ps.Length; i++) for (var i = 0; i < ps.Length; i++)
{ {
if (ops != null && ops.Length - 1 >= i) if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string))
{ {
ps[i] = ops[i]; ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default;
} }
else else
{ {
if (parameters[i].ParameterType.IsPrimitive || parameters[i].ParameterType == typeof(string)) if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
{ {
ps[i] = parameters[i].HasDefaultValue ? parameters[i].DefaultValue : default; var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? parameters[i].ParameterType;
ps[i] = this.Resolve(type, attribute.Key);
} }
else else
{ {
if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true)) ps[i] = this.Resolve(parameters[i].ParameterType, null);
{
var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? parameters[i].ParameterType;
ps[i] = this.Resolve(type, default, attribute.Key);
}
else
{
ps[i] = this.Resolve(parameters[i].ParameterType, null);
}
} }
} }
} }

View File

@@ -381,35 +381,11 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="container"></param> /// <param name="container"></param>
/// <param name="ps"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
public static T Resolve<T>(this IContainer container, object[] ps, string key = "") public static T Resolve<T>(this IContainer container, string key = "")
{ {
return (T)container.Resolve(typeof(T), ps, key); return (T)container.Resolve(typeof(T), key);
}
/// <summary>
/// 创建类型对应的实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static T Resolve<T>(this IContainer container)
{
return Resolve<T>(container, null);
}
/// <summary>
/// 创建类型对应的实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T Resolve<T>(this IContainer container, string key)
{
return Resolve<T>(container, null, key);
} }
/// <summary> /// <summary>
@@ -461,7 +437,7 @@ namespace ThingsGateway.Foundation.Core
{ {
var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>(); var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
var type = attribute.Type ?? parameters[i].ParameterType; var type = attribute.Type ?? parameters[i].ParameterType;
ps[i] = container.Resolve(type, default, attribute.Key); ps[i] = container.Resolve(type, attribute.Key);
} }
else else
{ {
@@ -489,47 +465,22 @@ namespace ThingsGateway.Foundation.Core
return (T)ResolveWithoutRoot(container, typeof(T)); return (T)ResolveWithoutRoot(container, typeof(T));
} }
/// <summary>
/// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <param name="ps"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T TryResolve<T>(this IContainer container, object[] ps, string key = "")
{
return (T)container.TryResolve(typeof(T), ps, key);
}
/// <summary> /// <summary>
/// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。 /// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。
/// </summary> /// </summary>
/// <param name="container"></param> /// <param name="container"></param>
/// <param name="fromType"></param> /// <param name="fromType"></param>
/// <param name="ps"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
public static object TryResolve(this IContainer container, Type fromType, object[] ps, string key = "") public static object TryResolve(this IContainer container, Type fromType, string key = "")
{ {
if (container.IsRegistered(fromType)) if (container.IsRegistered(fromType))
{ {
return container.Resolve(fromType, ps, key); return container.Resolve(fromType, key);
} }
return default; return default;
} }
/// <summary>
/// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="container"></param>
/// <returns></returns>
public static T TryResolve<T>(this IContainer container)
{
return TryResolve<T>(container, null);
}
/// <summary> /// <summary>
/// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。 /// 尝试创建类型对应的实例如果类型没有注册则会返回null或者默认值类型。
/// </summary> /// </summary>
@@ -537,9 +488,9 @@ namespace ThingsGateway.Foundation.Core
/// <param name="container"></param> /// <param name="container"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
public static T TryResolve<T>(this IContainer container, string key) public static T TryResolve<T>(this IContainer container, string key = "")
{ {
return TryResolve<T>(container, null, key); return (T)TryResolve(container, typeof(T), key);
} }
#endregion Resolve #endregion Resolve

View File

@@ -34,10 +34,9 @@ namespace ThingsGateway.Foundation.Core
/// 创建目标类型的对应实例。 /// 创建目标类型的对应实例。
/// </summary> /// </summary>
/// <param name="fromType"></param> /// <param name="fromType"></param>
/// <param name="ps"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
object Resolve(Type fromType, object[] ps = null, string key = ""); object Resolve(Type fromType, string key = "");
/// <summary> /// <summary>
/// 判断某类型是否已经注册 /// 判断某类型是否已经注册

View File

@@ -67,13 +67,13 @@ namespace ThingsGateway.Foundation.Core
/// <inheritdoc/> /// <inheritdoc/>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public object Resolve(Type fromType, object[] ps = null, string key = "") public object Resolve(Type fromType, string key = "")
{ {
if (fromType.FullName == "ThingsGateway.Foundation.Core.IContainer") if (fromType.FullName == "ThingsGateway.Foundation.Core.IContainer")
{ {
return this; return this;
} }
if (this.TryResolve(fromType, out var instance, ps, key)) if (this.TryResolve(fromType, out var instance, key))
{ {
return instance; return instance;
} }
@@ -100,10 +100,9 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
/// <param name="fromType"></param> /// <param name="fromType"></param>
/// <param name="instance"></param> /// <param name="instance"></param>
/// <param name="ps"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
protected virtual bool TryResolve(Type fromType, out object instance, object[] ps = null, string key = "") protected virtual bool TryResolve(Type fromType, out object instance, string key = "")
{ {
if (key.IsNullOrEmpty()) if (key.IsNullOrEmpty())
{ {

View File

@@ -22,6 +22,7 @@
// 感谢您的下载和使用 // 感谢您的下载和使用
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace ThingsGateway.Foundation.Core namespace ThingsGateway.Foundation.Core
{ {
/// <summary> /// <summary>
@@ -29,5 +30,24 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
public static class TaskExtension public static class TaskExtension
{ {
/// <summary>
/// 同步获取配置ConfigureAwait为false时的结果。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="task"></param>
/// <returns></returns>
public static T GetFalseAwaitResult<T>(this Task<T> task)
{
return task.ConfigureAwait(false).GetAwaiter().GetResult();
}
/// <summary>
/// 同步配置ConfigureAwait为false时的执行。
/// </summary>
/// <param name="task"></param>
public static void GetFalseAwaitResult(this Task task)
{
task.ConfigureAwait(false).GetAwaiter().GetResult();
}
} }
} }

View File

@@ -30,14 +30,6 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
public interface IPlugin : IDisposable public interface IPlugin : IDisposable
{ {
/// <summary>
/// 插件执行顺序
/// <para>该属性值越大,越靠前执行。值相等时,按添加先后顺序</para>
/// <para>该属性效果,仅在<see cref="IPluginsManager.Add(IPlugin)"/>之前设置有效。</para>
/// </summary>
[Obsolete("该属性已被弃用,插件顺序将直接由添加顺序决定。本设置将在正式版发布时直接删除", true)]
int Order { get; set; }
/// <summary> /// <summary>
/// 在插件被成功添加在<see cref="IPluginsManager"/>时执行。 /// 在插件被成功添加在<see cref="IPluginsManager"/>时执行。
/// </summary> /// </summary>

View File

@@ -17,9 +17,6 @@ namespace ThingsGateway.Foundation.Core
/// </summary> /// </summary>
public class PluginBase : DisposableObject, IPlugin public class PluginBase : DisposableObject, IPlugin
{ {
/// <inheritdoc/>
[Obsolete("该属性已被弃用,插件顺序将直接由添加顺序决定。本设置将在正式版发布时直接删除", true)]
public int Order { get; set; }
/// <inheritdoc cref="IPlugin.Loaded(IPluginsManager)"/> /// <inheritdoc cref="IPlugin.Loaded(IPluginsManager)"/>
protected virtual void Loaded(IPluginsManager pluginsManager) protected virtual void Loaded(IPluginsManager pluginsManager)

View File

@@ -184,7 +184,7 @@ namespace ThingsGateway.Foundation.Dmtp
} }
if (!this.Online) if (!this.Online)
{ {
await base.ConnectAsync(timeout); await base.ConnectAsync(timeout, token);
} }
var request = new HttpRequest() var request = new HttpRequest()
@@ -223,20 +223,20 @@ namespace ThingsGateway.Foundation.Dmtp
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task ReceivedData(ReceivedDataEventArgs e)
{ {
if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message) if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message)
{ {
if (!this.m_smtpActor.InputReceivedData(message)) if (!this.m_smtpActor.InputReceivedData(message))
{ {
if (this.PluginsManager.Enable) if (this.PluginsManager.Enable)
{ {
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message)); await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
} }
} }
return false; return;
} }
return base.HandleReceivedData(byteBlock, requestInfo); await base.ReceivedData(e);
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -251,9 +251,9 @@ namespace ThingsGateway.Foundation.Dmtp
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnDisconnected(DisconnectEventArgs e) protected override async Task OnDisconnected(DisconnectEventArgs e)
{ {
base.OnDisconnected(e); await base.OnDisconnected(e);
this.DmtpActor.Close(false, e.Message); this.DmtpActor.Close(false, e.Message);
} }

View File

@@ -62,10 +62,10 @@ namespace ThingsGateway.Foundation.Dmtp
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnConnected(TClient socketClient, ConnectedEventArgs e) protected override async Task OnConnected(TClient socketClient, ConnectedEventArgs e)
{ {
socketClient.m_internalOnRpcActorInit = this.PrivateOnRpcActorInit; socketClient.m_internalOnRpcActorInit = this.PrivateOnRpcActorInit;
base.OnConnected(socketClient, e); await base.OnConnected(socketClient, e);
} }
private IDmtpActor OnServiceFindDmtpActor(string id) private IDmtpActor OnServiceFindDmtpActor(string id)

View File

@@ -96,42 +96,55 @@ namespace ThingsGateway.Foundation.Dmtp
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/> /// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task ReceivedData(ReceivedDataEventArgs e)
{ {
if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message) if (this.Protocol == DmtpUtility.DmtpProtocol && e.RequestInfo is DmtpMessage message)
{ {
if (!this.m_smtpActor.InputReceivedData(message)) if (!this.m_smtpActor.InputReceivedData(message))
{ {
if (this.PluginsManager.Enable) await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
{
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
}
} }
return false;
}
else
{
return base.HandleReceivedData(byteBlock, requestInfo);
} }
await base.ReceivedData(e);
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnDisconnected(DisconnectEventArgs e) protected override async Task OnDisconnected(DisconnectEventArgs e)
{ {
this.DmtpActor?.Close(false, e.Message); this.DmtpActor?.Close(false, e.Message);
base.OnDisconnected(e); await base.OnDisconnected(e);
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
protected override void OnReceivedHttpRequest(HttpRequest request) protected override async Task OnReceivedHttpRequest(HttpRequest request)
{ {
if (request.IsMethod(DmtpUtility.Dmtp) && request.IsUpgrade() && if (request.IsMethod(DmtpUtility.Dmtp) && request.IsUpgrade() &&
string.Equals(request.Headers.Get(HttpHeaders.Upgrade), DmtpUtility.Dmtp, StringComparison.OrdinalIgnoreCase)) string.Equals(request.Headers.Get(HttpHeaders.Upgrade), DmtpUtility.Dmtp, StringComparison.OrdinalIgnoreCase))
@@ -142,7 +155,7 @@ namespace ThingsGateway.Foundation.Dmtp
this.DefaultSend(new HttpResponse().SetStatus(101, "Switching Protocols").BuildAsBytes()); this.DefaultSend(new HttpResponse().SetStatus(101, "Switching Protocols").BuildAsBytes());
return; return;
} }
base.OnReceivedHttpRequest(request); await base.OnReceivedHttpRequest(request);
} }
private void SetRpcActor(DmtpActor actor) private void SetRpcActor(DmtpActor actor)

View File

@@ -38,23 +38,24 @@ namespace ThingsGateway.Foundation.Dmtp
this.Protocol = DmtpUtility.DmtpProtocol; this.Protocol = DmtpUtility.DmtpProtocol;
} }
/// <inheritdoc/>
public IDmtpActor DmtpActor { get => this.m_smtpActor; }
/// <inheritdoc cref="IDmtpActor.Id"/> /// <inheritdoc cref="IDmtpActor.Id"/>
public string Id => this.DmtpActor.Id; public string Id => this.DmtpActor.Id;
#region #region
private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
private bool m_allowRoute; private bool m_allowRoute;
private Func<string, IDmtpActor> m_findDmtpActor; private Func<string, IDmtpActor> m_findDmtpActor;
private SealedDmtpActor m_smtpActor; private SealedDmtpActor m_smtpActor;
private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
#endregion #endregion
/// <inheritdoc cref="IDmtpActor.IsHandshaked"/> /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
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>
/// 发送<see cref="IDmtpActor"/>关闭消息。 /// 发送<see cref="IDmtpActor"/>关闭消息。
/// </summary> /// </summary>
@@ -153,7 +154,7 @@ namespace ThingsGateway.Foundation.Dmtp
} }
if (!this.Online) if (!this.Online)
{ {
await base.ConnectAsync(timeout); await base.ConnectAsync(timeout, token);
} }
await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty), await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
@@ -235,20 +236,6 @@ namespace ThingsGateway.Foundation.Dmtp
base.Dispose(disposing); base.Dispose(disposing);
} }
/// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
var message = (DmtpMessage)requestInfo;
if (!this.m_smtpActor.InputReceivedData(message))
{
if (this.PluginsManager.Enable)
{
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
}
}
return false;
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void LoadConfig(TouchSocketConfig config) protected override void LoadConfig(TouchSocketConfig config)
{ {
@@ -274,14 +261,31 @@ namespace ThingsGateway.Foundation.Dmtp
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnDisconnected(DisconnectEventArgs e) protected override async Task OnDisconnected(DisconnectEventArgs e)
{ {
base.OnDisconnected(e); await base.OnDisconnected(e);
this.DmtpActor.Close(false, e.Message); this.DmtpActor.Close(false, e.Message);
} }
/// <inheritdoc/>
protected override async Task ReceivedData(ReceivedDataEventArgs e)
{
var message = (DmtpMessage)e.RequestInfo;
if (!this.m_smtpActor.InputReceivedData(message))
{
await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
}
await base.ReceivedData(e);
}
#region #region
private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
{
base.Send(transferBytes);
}
private void OnDmtpActorClose(DmtpActor actor, string msg) private void OnDmtpActorClose(DmtpActor actor, string msg)
{ {
base.Close(msg); base.Close(msg);
@@ -330,11 +334,6 @@ namespace ThingsGateway.Foundation.Dmtp
this.OnRouting(e); this.OnRouting(e);
} }
private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
{
base.Send(transferBytes);
}
#endregion #endregion
#region #region

View File

@@ -68,14 +68,14 @@ namespace ThingsGateway.Foundation.Dmtp
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnConnecting(TClient socketClient, ConnectingEventArgs e) protected override async Task OnConnecting(TClient socketClient, ConnectingEventArgs e)
{ {
socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute) socketClient.SetDmtpActor(new SealedDmtpActor(this.m_allowRoute)
{ {
Id = e.Id, Id = e.Id,
OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null
}); });
base.OnConnecting(socketClient, e); await base.OnConnecting(socketClient, e);
} }
private IDmtpActor OnServiceFindDmtpActor(string id) private IDmtpActor OnServiceFindDmtpActor(string id)

View File

@@ -40,12 +40,12 @@ namespace ThingsGateway.Foundation.Dmtp
this.Protocol = DmtpUtility.DmtpProtocol; this.Protocol = DmtpUtility.DmtpProtocol;
} }
/// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
/// <inheritdoc/> /// <inheritdoc/>
public IDmtpActor DmtpActor { get => this.m_smtpActor; } public IDmtpActor DmtpActor { get => this.m_smtpActor; }
/// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
/// <summary> /// <summary>
/// 验证超时时间,默认为3000ms /// 验证超时时间,默认为3000ms
/// </summary> /// </summary>
@@ -201,26 +201,23 @@ namespace ThingsGateway.Foundation.Dmtp
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task ReceivedData(ReceivedDataEventArgs e)
{ {
var message = (DmtpMessage)requestInfo; var message = (DmtpMessage)e.RequestInfo;
if (!this.m_smtpActor.InputReceivedData(message)) if (!this.m_smtpActor.InputReceivedData(message))
{ {
if (this.PluginsManager.Enable) await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
{
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
}
} }
return false; await base.ReceivedData(e);
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnConnected(ConnectedEventArgs e) protected override async Task OnConnected(ConnectedEventArgs e)
{ {
this.m_smtpActor.Id = this.Id; this.m_smtpActor.Id = this.Id;
base.OnConnected(e); await base.OnConnected(e);
Task.Run(async () => _ = Task.Run(async () =>
{ {
await Task.Delay(this.VerifyTimeout); await Task.Delay(this.VerifyTimeout);
if (!this.IsHandshaked) if (!this.IsHandshaked)
@@ -232,15 +229,10 @@ namespace ThingsGateway.Foundation.Dmtp
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnDisconnected(DisconnectEventArgs e) protected override async Task OnDisconnected(DisconnectEventArgs e)
{ {
this.DmtpActor.Close(false, e.Message); this.DmtpActor.Close(false, e.Message);
base.OnDisconnected(e); await base.OnDisconnected(e);
}
private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId)
{
this.DirectResetId(waitSetId.NewId);
} }
private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes) private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
@@ -248,6 +240,11 @@ namespace ThingsGateway.Foundation.Dmtp
base.Send(transferBytes); base.Send(transferBytes);
} }
private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId)
{
this.DirectResetId(waitSetId.NewId);
}
#region #region
/// <summary> /// <summary>

View File

@@ -75,20 +75,20 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task ReceivedData(UdpReceivedDataEventArgs e)
{ {
var client = this.PrivateGetUdpDmtpClient(remoteEndPoint); var client = this.PrivateGetUdpDmtpClient(e.EndPoint);
if (client == null) if (client == null)
{ {
return; return;
} }
var message = DmtpMessage.CreateFrom(byteBlock); var message = DmtpMessage.CreateFrom(e.ByteBlock);
if (!client.InputReceivedData(message)) if (!client.InputReceivedData(message))
{ {
if (this.PluginsManager.Enable) if (this.PluginsManager.Enable)
{ {
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), client, new DmtpMessageEventArgs(message)); await this.PluginsManager.RaiseAsync(nameof(IDmtpReceivedPlugin.OnDmtpReceived), client, new DmtpMessageEventArgs(message));
} }
} }
} }

View File

@@ -49,9 +49,7 @@ namespace ThingsGateway.Foundation.Dmtp
} }
#region #region
#pragma warning disable CS0414
private bool m_allowRoute;
#pragma warning restore CS0414
private ClientWebSocket m_client; private ClientWebSocket m_client;
private Func<string, IDmtpActor> m_findDmtpActor; private Func<string, IDmtpActor> m_findDmtpActor;
private ValueCounter m_receiveCounter; private ValueCounter m_receiveCounter;
@@ -236,18 +234,6 @@ namespace ThingsGateway.Foundation.Dmtp
this.DmtpActor.ResetId(newId); this.DmtpActor.ResetId(newId);
} }
/// <summary>
/// 配置
/// </summary>
/// <param name="ipHost"></param>
/// <returns></returns>
public IWebSocketDmtpClient Setup(string ipHost)
{
var config = new TouchSocketConfig();
config.SetRemoteIPHost(new IPHost(ipHost));
return this.Setup(config);
}
/// <summary> /// <summary>
/// 配置 /// 配置
/// </summary> /// </summary>
@@ -297,7 +283,6 @@ namespace ThingsGateway.Foundation.Dmtp
if (this.Container.IsRegistered(typeof(IDmtpRouteService))) if (this.Container.IsRegistered(typeof(IDmtpRouteService)))
{ {
this.m_allowRoute = true;
this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor; this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor;
} }
} }
@@ -421,10 +406,7 @@ namespace ThingsGateway.Foundation.Dmtp
var message = (DmtpMessage)requestInfo; var message = (DmtpMessage)requestInfo;
if (!this.m_dmtpActor.InputReceivedData(message)) if (!this.m_dmtpActor.InputReceivedData(message))
{ {
if (this.PluginsManager.Enable) this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
{
this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
}
} }
} }
@@ -534,5 +516,28 @@ namespace ThingsGateway.Foundation.Dmtp
} }
#endregion #endregion
#region Receiver
/// <summary>
/// 不支持该功能
/// </summary>
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
public IReceiver CreateReceiver()
{
throw new NotSupportedException("不支持该功能");
}
/// <summary>
/// 不支持该功能
/// </summary>
/// <exception cref="NotSupportedException"></exception>
public void ClearReceiver()
{
throw new NotSupportedException("不支持该功能");
}
#endregion
} }
} }

View File

@@ -1507,7 +1507,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
waitFileSection.Message = ex.Message; waitFileSection.Message = ex.Message;
} }
waitFileSection.Value.Dispose(); waitFileSection.Value.SafeDispose();
waitFileSection.Value = default; waitFileSection.Value = default;
using (var byteBlock = new ByteBlock()) using (var byteBlock = new ByteBlock())
{ {

View File

@@ -213,14 +213,11 @@ namespace ThingsGateway.Foundation.Http
base.Dispose(disposing); base.Dispose(disposing);
} }
/// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> protected override Task ReceivedData(ReceivedDataEventArgs e)
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
if (requestInfo is HttpResponse response) if (e.RequestInfo is HttpResponse response)
{ {
if (this.m_getContent) if (this.m_getContent)
{ {
@@ -229,18 +226,18 @@ namespace ThingsGateway.Foundation.Http
this.m_waitData.Set(response); this.m_waitData.Set(response);
} }
return false; return base.ReceivedData(e);
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnConnecting(ConnectingEventArgs e) protected override async Task OnConnecting(ConnectingEventArgs e)
{ {
this.Protocol = Protocol.Http; this.Protocol = Protocol.Http;
this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter()); this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter());
base.OnConnecting(e); await base.OnConnecting(e);
} }
} }
} }

View File

@@ -20,6 +20,8 @@ using System.Threading.Tasks;
using ThingsGateway.Foundation.Core; using ThingsGateway.Foundation.Core;
using ThingsGateway.Foundation.Sockets; using ThingsGateway.Foundation.Sockets;
using HttpClient = System.Net.Http.HttpClient;
using HttpMethod = System.Net.Http.HttpMethod;
namespace ThingsGateway.Foundation.Http namespace ThingsGateway.Foundation.Http
{ {
@@ -100,16 +102,6 @@ namespace ThingsGateway.Foundation.Http
return this; return this;
} }
/// <summary>
/// 配置
/// </summary>
/// <param name="remoteIPHost"></param>
/// <returns></returns>
public HttpClientSlim Setup(string remoteIPHost)
{
return this.Setup(new TouchSocketConfig().SetRemoteIPHost(remoteIPHost));
}
private void BuildConfig(TouchSocketConfig config) private void BuildConfig(TouchSocketConfig config)
{ {
this.Config = config; this.Config = config;

View File

@@ -39,34 +39,35 @@ namespace ThingsGateway.Foundation.Http
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnConnecting(ConnectingEventArgs e) protected override async Task OnConnecting(ConnectingEventArgs e)
{ {
this.SetDataHandlingAdapter(new HttpServerDataHandlingAdapter()); this.SetDataHandlingAdapter(new HttpServerDataHandlingAdapter());
base.OnConnecting(e); await base.OnConnecting(e);
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task ReceivedData(ReceivedDataEventArgs e)
{ {
if (requestInfo is HttpRequest request) if (e.RequestInfo is HttpRequest request)
{ {
this.OnReceivedHttpRequest(request); await this.OnReceivedHttpRequest(request);
} }
await base.ReceivedData(e);
return false;
} }
/// <summary> /// <summary>
/// 当收到到Http请求时。覆盖父类方法将不会触发插件。 /// 当收到到Http请求时。覆盖父类方法将不会触发插件。
/// </summary> /// </summary>
protected virtual void OnReceivedHttpRequest(HttpRequest request) protected virtual Task OnReceivedHttpRequest(HttpRequest request)
{ {
if (this.PluginsManager.GetPluginCount(nameof(IHttpPlugin.OnHttpRequest)) > 0) if (this.PluginsManager.GetPluginCount(nameof(IHttpPlugin.OnHttpRequest)) > 0)
{ {
var e = new HttpContextEventArgs(new HttpContext(request)); var e = new HttpContextEventArgs(new HttpContext(request));
this.PluginsManager.Raise(nameof(IHttpPlugin.OnHttpRequest), this, e); return this.PluginsManager.RaiseAsync(nameof(IHttpPlugin.OnHttpRequest), this, e);
} }
return EasyTask.CompletedTask;
} }
} }
} }

View File

@@ -1,37 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Http
{
/// <summary>
/// IHttpDeletePlugin
/// </summary>
[Obsolete("该插件已被弃用请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
public interface IHttpDeletePlugin<in TClient> : IPlugin where TClient : IHttpSocketClient
{
/// <summary>
/// 在收到Delete时
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
Task OnHttpDelete(TClient client, HttpContextEventArgs e);
}
/// <summary>
/// IHttpDeletePlugin
/// </summary>
[Obsolete("该插件已被弃用请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
public interface IHttpDeletePlugin : IHttpDeletePlugin<IHttpSocketClient>
{
}
}

View File

@@ -1,37 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Http
{
/// <summary>
/// IHttpGetPlugin
/// </summary>
[Obsolete("该插件已被弃用请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
public interface IHttpGetPlugin<in TClient> : IPlugin where TClient : IHttpSocketClient
{
/// <summary>
/// 在收到Get时
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
Task OnHttpGet(TClient client, HttpContextEventArgs e);
}
/// <summary>
/// IHttpGetPlugin
/// </summary>
[Obsolete("该插件已被弃用请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
public interface IHttpGetPlugin : IHttpGetPlugin<IHttpSocketClient>
{
}
}

View File

@@ -31,8 +31,7 @@ namespace ThingsGateway.Foundation.Http
public interface IHttpPlugin<in TClient> : IPlugin where TClient : IHttpSocketClient public interface IHttpPlugin<in TClient> : IPlugin where TClient : IHttpSocketClient
{ {
/// <summary> /// <summary>
/// 在收到Http请求时。注意:此插件的执行在<see cref="IHttpGetPlugin"/>,<see cref="IHttpPostPlugin"/>, /// 在收到Http请求时
/// <see cref="IHttpDeletePlugin"/>,<see cref="IHttpPutPlugin"/>之前。
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="e"></param> /// <param name="e"></param>

View File

@@ -1,37 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
namespace ThingsGateway.Foundation.Http
{
/// <summary>
/// IHttpPostPlugin
/// </summary>
[Obsolete("该插件已被弃用请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
public interface IHttpPostPlugin<in TClient> : IPlugin where TClient : IHttpSocketClient
{
/// <summary>
/// 在收到Post时
/// </summary>
/// <param name="client"></param>
/// <param name="e"></param>
/// <returns></returns>
Task OnHttpPost(TClient client, HttpContextEventArgs e);
}
/// <summary>
/// IHttpPostPlugin
/// </summary>
[Obsolete("该插件已被弃用请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
public interface IHttpPostPlugin : IHttpPostPlugin<IHttpSocketClient>
{
}
}

View File

@@ -75,7 +75,17 @@ namespace ThingsGateway.Foundation.Http.WebSockets
await this.m_resetEventForRead.WaitOneAsync(token); await this.m_resetEventForRead.WaitOneAsync(token);
return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame); return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame);
} }
#if NET6_0_OR_GREATER
public async ValueTask<WebSocketReceiveResult> ValueReadAsync(CancellationToken token)
{
if (!this.m_receive)
{
return new WebSocketReceiveResult(this.ComplateRead, null);
}
await this.m_resetEventForRead.WaitOneAsync(token);
return new WebSocketReceiveResult(this.ComplateRead, this.m_dataFrame);
}
#endif
#region #region
public void Send(WSDataFrame dataFrame, bool endOfMessage = true) public void Send(WSDataFrame dataFrame, bool endOfMessage = true)
{ {
@@ -145,7 +155,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
this.m_client.RemoveValue(WebSocketClientExtensions.WebSocketProperty); this.m_client.RemoveValue(WebSocketClientExtension.WebSocketProperty);
this.m_resetEventForComplateRead.SafeDispose(); this.m_resetEventForComplateRead.SafeDispose();
this.m_resetEventForRead.SafeDispose(); this.m_resetEventForRead.SafeDispose();
this.m_dataFrame = null; this.m_dataFrame = null;
@@ -154,8 +164,8 @@ namespace ThingsGateway.Foundation.Http.WebSockets
private void ComplateRead() private void ComplateRead()
{ {
this.m_resetEventForComplateRead.Set();
this.m_dataFrame = default; this.m_dataFrame = default;
this.m_resetEventForComplateRead.Set();
} }
} }
} }

View File

@@ -41,5 +41,10 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// WebSocket数据帧 /// WebSocket数据帧
/// </summary> /// </summary>
public WSDataFrame DataFrame { get; private set; } public WSDataFrame DataFrame { get; private set; }
/// <summary>
/// 连接已关闭
/// </summary>
public bool IsClosed => this.DataFrame == null;
} }
} }

View File

@@ -39,10 +39,14 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="dataFrame"></param> /// <param name="dataFrame"></param>
protected override void OnHandleWSDataFrame(WSDataFrame dataFrame) protected override async Task OnReceivedWSDataFrame(WSDataFrame dataFrame)
{ {
this.Received?.Invoke(this, dataFrame); if (this.Received != null)
base.OnHandleWSDataFrame(dataFrame); {
await this.Received.Invoke(this, dataFrame);
}
await base.OnReceivedWSDataFrame(dataFrame);
} }
} }
@@ -211,20 +215,44 @@ namespace ThingsGateway.Foundation.Http.WebSockets
#endregion #endregion
///// <inheritdoc/>
//protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
//{
// if (this.GetHandshaked())
// {
// var dataFrame = (WSDataFrame)requestInfo;
// this.OnReceivedWSDataFrame(dataFrame);
// }
// else
// {
// if (requestInfo is HttpResponse response)
// {
// response.Flag = false;
// base.HandleReceivedData(byteBlock, requestInfo);
// SpinWait.SpinUntil(() =>
// {
// return (bool)response.Flag;
// }, 3000);
// }
// }
// return false;
//}
/// <inheritdoc/> /// <inheritdoc/>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) protected override async Task ReceivedData(ReceivedDataEventArgs e)
{ {
if (this.GetHandshaked()) if (this.GetHandshaked())
{ {
var dataFrame = (WSDataFrame)requestInfo; var dataFrame = (WSDataFrame)e.RequestInfo;
this.OnHandleWSDataFrame(dataFrame); await this.OnReceivedWSDataFrame(dataFrame);
} }
else else
{ {
if (requestInfo is HttpResponse response) if (e.RequestInfo is HttpResponse response)
{ {
response.Flag = false; response.Flag = false;
base.HandleReceivedData(byteBlock, requestInfo); await base.ReceivedData(e);
SpinWait.SpinUntil(() => SpinWait.SpinUntil(() =>
{ {
return (bool)response.Flag; return (bool)response.Flag;
@@ -232,32 +260,32 @@ namespace ThingsGateway.Foundation.Http.WebSockets
} }
} }
return false; await base.ReceivedData(e);
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnDisconnected(DisconnectEventArgs e) protected override async Task OnDisconnected(DisconnectEventArgs e)
{ {
this.SetValue(WebSocketFeature.HandshakedProperty, false); this.SetValue(WebSocketFeature.HandshakedProperty, false);
if (this.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket)) if (this.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
{ {
_ = internalWebSocket.TryInputReceiveAsync(null); _ = internalWebSocket.TryInputReceiveAsync(null);
} }
base.OnDisconnected(e); await base.OnDisconnected(e);
} }
/// <summary> /// <summary>
/// 当收到WS数据时。 /// 当收到WS数据时。
/// </summary> /// </summary>
/// <param name="dataFrame"></param> /// <param name="dataFrame"></param>
protected virtual void OnHandleWSDataFrame(WSDataFrame dataFrame) protected virtual async Task OnReceivedWSDataFrame(WSDataFrame dataFrame)
{ {
if (this.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket)) if (this.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
{ {
if (internalWebSocket.TryInputReceiveAsync(dataFrame).ConfigureAwait(false).GetAwaiter().GetResult()) if (await internalWebSocket.TryInputReceiveAsync(dataFrame))
{ {
return; return;
} }
@@ -265,7 +293,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
if (this.PluginsManager.Enable) if (this.PluginsManager.Enable)
{ {
this.PluginsManager.Raise(nameof(IWebSocketReceivedPlugin.OnWebSocketReceived), this, new WSDataFrameEventArgs(dataFrame)); await this.PluginsManager.RaiseAsync(nameof(IWebSocketReceivedPlugin.OnWebSocketReceived), this, new WSDataFrameEventArgs(dataFrame));
} }
} }
} }

View File

@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <summary> /// <summary>
/// WebSocket适配器 /// WebSocket适配器
/// </summary> /// </summary>
public class WebSocketDataHandlingAdapter : SingleStreamDataHandlingAdapter public sealed class WebSocketDataHandlingAdapter : SingleStreamDataHandlingAdapter
{ {
private WSDataFrame m_dataFrameTemp; private WSDataFrame m_dataFrameTemp;
@@ -42,16 +42,6 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// </summary> /// </summary>
private ByteBlock m_tempByteBlock; private ByteBlock m_tempByteBlock;
/// <summary>
/// <inheritdoc/>
/// </summary>
public override bool CanSendRequestInfo => false;
/// <summary>
/// <inheritdoc/>
/// </summary>
public override bool CanSplicingSend => false;
/// <summary> /// <summary>
/// 解码 /// 解码
/// </summary> /// </summary>
@@ -183,35 +173,6 @@ namespace ThingsGateway.Foundation.Http.WebSockets
} }
} }
/// <summary>
/// 当发送数据前处理数据
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
protected override void PreviewSend(byte[] buffer, int offset, int length)
{
this.GoSend(buffer, offset, length);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="transferBytes"></param>
protected override void PreviewSend(IList<ArraySegment<byte>> transferBytes)
{
throw new System.NotImplementedException();//因为设置了不支持拼接发送,所以该方法可以不实现。
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="requestInfo"></param>
protected override void PreviewSend(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>

View File

@@ -30,5 +30,5 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="dataFrame"></param> /// <param name="dataFrame"></param>
public delegate void WSDataFrameEventHandler<TClient>(TClient client, WSDataFrame dataFrame); public delegate Task WSDataFrameEventHandler<TClient>(TClient client, WSDataFrame dataFrame);
} }

View File

@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <summary> /// <summary>
/// WSClientExtensions /// WSClientExtensions
/// </summary> /// </summary>
public static class WebSocketClientExtensions public static class WebSocketClientExtension
{ {
#region DependencyProperty #region DependencyProperty

View File

@@ -29,7 +29,7 @@ namespace ThingsGateway.Foundation.Sockets
/// <summary> /// <summary>
/// WebSocketConfigExtensions /// WebSocketConfigExtensions
/// </summary> /// </summary>
public static class WebSocketConfigExtensions public static class WebSocketConfigExtension
{ {
/// <summary> /// <summary>
/// 构建WebSocketClient类客户端并连接 /// 构建WebSocketClient类客户端并连接

View File

@@ -29,7 +29,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <summary> /// <summary>
/// WSDataFrame辅助扩展类 /// WSDataFrame辅助扩展类
/// </summary> /// </summary>
public static class WebSocketDataFrameExtensions public static class WebSocketDataFrameExtension
{ {
/// <summary> /// <summary>
/// 追加二进制流 /// 追加二进制流

View File

@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <summary> /// <summary>
/// WebSocketServerExtensions /// WebSocketServerExtensions
/// </summary> /// </summary>
public static class WebSocketServerExtensions public static class WebSocketServerExtension
{ {
/// <summary> /// <summary>
/// 转化Protocol协议标识为<see cref="Protocol.WebSocket"/> /// 转化Protocol协议标识为<see cref="Protocol.WebSocket"/>
@@ -49,7 +49,8 @@ namespace ThingsGateway.Foundation.Http.WebSockets
{ {
IsPermitOperation = true IsPermitOperation = true
}; };
await client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakingPlugin.OnWebSocketHandshaking), client, args); await client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakingPlugin.OnWebSocketHandshaking), client, args).ConfigureAwait(false);
if (args.Context.Response.Responsed) if (args.Context.Response.Responsed)
{ {
return false; return false;
@@ -63,9 +64,10 @@ namespace ThingsGateway.Foundation.Http.WebSockets
using (var byteBlock = new ByteBlock()) using (var byteBlock = new ByteBlock())
{ {
args.Context.Response.Build(byteBlock); args.Context.Response.Build(byteBlock);
await client.DefaultSendAsync(byteBlock); await client.DefaultSendAsync(byteBlock).ConfigureAwait(false);
} }
await client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), client, new HttpContextEventArgs(httpContext)); await client.PluginsManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), client, new HttpContextEventArgs(httpContext))
.ConfigureAwait(false);
return true; return true;
} }
else else
@@ -74,7 +76,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
using (var byteBlock = new ByteBlock()) using (var byteBlock = new ByteBlock())
{ {
args.Context.Response.Build(byteBlock); args.Context.Response.Build(byteBlock);
await client.DefaultSendAsync(byteBlock); await client.DefaultSendAsync(byteBlock).ConfigureAwait(false);
} }
client.Close("主动拒绝WebSocket连接"); client.Close("主动拒绝WebSocket连接");

View File

@@ -68,7 +68,14 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<WebSocketReceiveResult> ReadAsync(CancellationToken token); Task<WebSocketReceiveResult> ReadAsync(CancellationToken token);
#if NET6_0_OR_GREATER
/// <summary>
/// 值异步等待读取数据
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public ValueTask<WebSocketReceiveResult> ValueReadAsync(CancellationToken token);
#endif
/// <summary> /// <summary>
/// 采用WebSocket协议发送WS数据。发送结束后请及时释放<see cref="WSDataFrame"/> /// 采用WebSocket协议发送WS数据。发送结束后请及时释放<see cref="WSDataFrame"/>
/// </summary> /// </summary>

View File

@@ -71,7 +71,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <summary> /// <summary>
/// 验证连接 /// 验证连接
/// </summary> /// </summary>
public Func<IHttpSocketClient, HttpContext, bool> VerifyConnection { get; set; } public Func<IHttpSocketClient, HttpContext, Task<bool>> VerifyConnection { get; set; }
/// <summary> /// <summary>
/// 用于WebSocket连接的路径默认为“/ws” /// 用于WebSocket连接的路径默认为“/ws”
@@ -98,7 +98,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
{ {
if (client.Protocol == Protocol.Http) if (client.Protocol == Protocol.Http)
{ {
if (this.VerifyConnection.Invoke(client, e.Context)) if (await this.VerifyConnection.Invoke(client, e.Context))
{ {
e.Handled = true; e.Handled = true;
_ = client.SwitchProtocolToWebSocket(e.Context); _ = client.SwitchProtocolToWebSocket(e.Context);
@@ -117,7 +117,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
public async Task OnTcpDisconnected(ITcpClientBase client, DisconnectEventArgs e) public async Task OnTcpDisconnected(ITcpClientBase client, DisconnectEventArgs e)
{ {
client.SetValue(HandshakedProperty, false); client.SetValue(HandshakedProperty, false);
if (client.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket)) if (client.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
{ {
_ = internalWebSocket.TryInputReceiveAsync(null); _ = internalWebSocket.TryInputReceiveAsync(null);
} }
@@ -145,6 +145,21 @@ namespace ThingsGateway.Foundation.Http.WebSockets
/// <param name="func"></param> /// <param name="func"></param>
/// <returns></returns> /// <returns></returns>
public WebSocketFeature SetVerifyConnection(Func<IHttpSocketClient, HttpContext, bool> func) public WebSocketFeature SetVerifyConnection(Func<IHttpSocketClient, HttpContext, bool> func)
{
this.VerifyConnection = async (client, context) =>
{
await EasyTask.CompletedTask;
return func.Invoke(client, context);
};
return this;
}
/// <summary>
/// 验证连接
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
public WebSocketFeature SetVerifyConnection(Func<IHttpSocketClient, HttpContext, Task<bool>> func)
{ {
this.VerifyConnection = func; this.VerifyConnection = func;
return this; return this;
@@ -186,7 +201,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
((HttpSocketClient)client).PongWS(); ((HttpSocketClient)client).PongWS();
return; return;
} }
if (client.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket)) if (client.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
{ {
if (await internalWebSocket.TryInputReceiveAsync(dataFrame)) if (await internalWebSocket.TryInputReceiveAsync(dataFrame))
{ {
@@ -196,8 +211,9 @@ namespace ThingsGateway.Foundation.Http.WebSockets
await this.m_pluginsManager.RaiseAsync(nameof(IWebSocketReceivedPlugin.OnWebSocketReceived), client, new WSDataFrameEventArgs(dataFrame)); await this.m_pluginsManager.RaiseAsync(nameof(IWebSocketReceivedPlugin.OnWebSocketReceived), client, new WSDataFrameEventArgs(dataFrame));
} }
private bool ThisVerifyConnection(IHttpSocketClient client, HttpContext context) private async Task<bool> ThisVerifyConnection(IHttpSocketClient client, HttpContext context)
{ {
await EasyTask.CompletedTask;
if (context.Request.Method == HttpMethod.Get) if (context.Request.Method == HttpMethod.Get)
{ {
if (this.WSUrl == "/" || context.Request.UrlEquals(this.WSUrl)) if (this.WSUrl == "/" || context.Request.UrlEquals(this.WSUrl))

View File

@@ -41,12 +41,6 @@ namespace ThingsGateway.Foundation.Rpc
/// </summary> /// </summary>
ExtensionAsync = 2, ExtensionAsync = 2,
/// <summary>
/// 包含扩展(源代码生成无效)
/// </summary>
[Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
IncludeExtension = 4,
/// <summary> /// <summary>
/// 生成实例类同步代码(源代码生成无效) /// 生成实例类同步代码(源代码生成无效)
/// </summary> /// </summary>

View File

@@ -19,7 +19,7 @@ namespace ThingsGateway.Foundation.Serial;
/// <typeparam name="TClient"></typeparam> /// <typeparam name="TClient"></typeparam>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="e"></param> /// <param name="e"></param>
public delegate void SerialConnectingEventHandler<TClient>(TClient client, SerialConnectingEventArgs e); public delegate Task SerialConnectingEventHandler<TClient>(TClient client, SerialConnectingEventArgs e);
/// <summary> /// <summary>
/// 客户端连接事件。 /// 客户端连接事件。

View File

@@ -15,21 +15,7 @@ namespace ThingsGateway.Foundation.Serial;
/// <summary> /// <summary>
/// 串口基接口 /// 串口基接口
/// </summary> /// </summary>
public interface ISerial : IDisposable public interface ISerial : ISocket
{ {
/// <summary>
/// 发送缓存区大小。最小值=1024。
/// </summary>
int SendBufferSize { get; set; }
/// <summary>
/// 接收缓存区大小。最小值=1024。
/// </summary>
int ReceiveBufferSize { get; set; }
/// <summary>
/// 日志记录器
/// </summary>
ILog Logger { get; set; }
} }

View File

@@ -53,9 +53,9 @@ public interface ISerialSessionBase : IClient, ISender, IDefaultSender, IPluginO
/// <summary> /// <summary>
/// 接收模式 /// 判断是否在线
/// </summary> /// </summary>
public ReceiveType ReceiveType { get; } bool Online { get; }
/// <summary> /// <summary>
/// 串口描述 /// 串口描述

View File

@@ -21,21 +21,23 @@ public abstract class BaseSerial : DependencyObject, ISerial
/// 同步根。 /// 同步根。
/// </summary> /// </summary>
protected readonly object SyncRoot = new object(); protected readonly object SyncRoot = new object();
private int m_receiveBufferSize = 1024 * 64; private int m_receiveBufferSize = 1024 * 10;
private int m_sendBufferSize = 1024 * 64; private int m_sendBufferSize = 1024 * 10;
/// <inheritdoc/> /// <inheritdoc/>
public virtual int SendBufferSize public virtual int SendBufferSize
{ {
get => m_sendBufferSize; get => this.m_sendBufferSize;
set => m_sendBufferSize = value < 1024 ? 1024 : value; set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual int ReceiveBufferSize public virtual int ReceiveBufferSize
{ {
get => m_receiveBufferSize; get => this.m_receiveBufferSize;
set => m_receiveBufferSize = value < 1024 ? 1024 : value; set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
} }
/// <inheritdoc/> /// <inheritdoc/>
public ILog Logger { get; set; } public ILog Logger { get; set; }
} }

View File

@@ -0,0 +1,396 @@
#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.Diagnostics;
using System.IO.Ports;
namespace ThingsGateway.Foundation.Serial;
internal sealed class InternalSerialCore : SerialCore
{
}
/// <summary>
/// Serial核心
/// </summary>
public class SerialCore : IDisposable, ISender
{
/// <summary>
/// 初始缓存大小
/// </summary>
public const int BufferSize = 1024 * 10;
#region
/// <summary>
/// 同步根
/// </summary>
public readonly object SyncRoot = new object();
private long m_bufferRate;
private bool m_disposedValue;
private SpinLock m_lock;
private bool m_online => MainSerialPort?.IsOpen == true;
private int m_receiveBufferSize = BufferSize;
private ValueCounter m_receiveCounter;
private int m_sendBufferSize = BufferSize;
private ValueCounter m_sendCounter;
private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
#endregion
/// <summary>
/// Tcp核心
/// </summary>
public SerialCore()
{
this.m_lock = new SpinLock(Debugger.IsAttached);
this.m_receiveCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnReceivePeriod
};
this.m_sendCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnSendPeriod
};
}
/// <summary>
/// 析构函数
/// </summary>
~SerialCore()
{
this.Dispose(disposing: false);
}
/// <inheritdoc/>
public bool CanSend => this.m_online;
/// <summary>
/// 当中断Tcp的时候。当为<see langword="true"/>时,意味着是调用<see cref="Close(string)"/>。当为<see langword="false"/>时,则是其他中断。
/// </summary>
public Action<SerialCore, bool, string> OnBreakOut { get; set; }
/// <summary>
/// 当发生异常的时候
/// </summary>
public Action<SerialCore, Exception> OnException { get; set; }
/// <summary>
/// 在线状态
/// </summary>
public bool Online { get => this.m_online; }
/// <summary>
/// UserToken
/// </summary>
public ByteBlock UserToken { get; set; }
/// <summary>
/// 当收到数据的时候
/// </summary>
public Action<SerialCore, ByteBlock> OnReceived { get; set; }
/// <summary>
/// 接收缓存池(可以设定初始值,运行时的值会根据流速自动调整)
/// </summary>
public int ReceiveBufferSize
{
get => this.m_receiveBufferSize;
set
{
this.m_receiveBufferSize = value;
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.ReadBufferSize = value;
}
}
}
/// <summary>
/// 接收计数器
/// </summary>
public ValueCounter ReceiveCounter { get => this.m_receiveCounter; }
/// <summary>
/// 发送缓存池(可以设定初始值,运行时的值会根据流速自动调整)
/// </summary>
public int SendBufferSize
{
get => this.m_sendBufferSize;
set
{
this.m_sendBufferSize = value;
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.WriteBufferSize = value;
}
}
}
/// <summary>
/// 发送计数器
/// </summary>
public ValueCounter SendCounter { get => this.m_sendCounter; }
/// <summary>
/// SerialPort
/// </summary>
public SerialPort MainSerialPort { get; private set; }
/// <summary>
/// 开始以Iocp方式接收
/// </summary>
public virtual void BeginIocpReceive()
{
var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
this.UserToken = byteBlock;
byteBlock.SetLength(0);
if (this.MainSerialPort.BytesToRead > 0)
{
this.ProcessReceived();
}
MainSerialPort.DataReceived += MainSerialPort_DataReceived;
}
private void MainSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
this.m_bufferRate = 1;
this.ProcessReceived();
}
catch (Exception ex)
{
this.PrivateBreakOut(false, ex.Message);
}
}
/// <summary>
/// 请求关闭
/// </summary>
/// <param name="msg"></param>
public virtual void Close(string msg)
{
this.PrivateBreakOut(true, msg);
}
/// <summary>
/// 释放对象
/// </summary>
public void Dispose()
{
this.Dispose(disposing: true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 重置环境,并设置新的<see cref="MainSerialPort"/>。
/// </summary>
/// <param name="socket"></param>
public virtual void Reset(SerialPort socket)
{
if (socket is null)
{
throw new ArgumentNullException(nameof(socket));
}
if (!socket.IsOpen)
{
throw new Exception("新的SerialPort必须在连接状态。");
}
this.Reset();
this.MainSerialPort = socket;
}
/// <summary>
/// 重置环境。
/// </summary>
public virtual void Reset()
{
this.m_receiveCounter.Reset();
this.m_sendCounter.Reset();
this.MainSerialPort = null;
this.OnReceived = null;
this.OnBreakOut = null;
this.UserToken = null;
this.m_bufferRate = 1;
this.m_lock = new SpinLock();
this.m_receiveBufferSize = BufferSize;
this.m_sendBufferSize = BufferSize;
}
/// <summary>
/// 发送数据。
/// <para>
/// 内部会根据是否启用Ssl进行直接发送还是Ssl发送。
/// </para>
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public virtual void Send(byte[] buffer, int offset, int length)
{
var lockTaken = false;
try
{
this.m_lock.Enter(ref lockTaken);
this.MainSerialPort.Write(buffer, offset, length);
}
finally
{
if (lockTaken) this.m_lock.Exit(false);
}
this.m_sendCounter.Increment(length);
}
/// <summary>
/// 异步发送数据。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public virtual async Task SendAsync(byte[] buffer, int offset, int length)
{
try
{
await this.m_semaphore.WaitAsync();
this.MainSerialPort.Write(buffer, offset, length);
}
finally
{
this.m_semaphore.Release();
}
this.m_sendCounter.Increment(length);
}
/// <summary>
/// 当中断Tcp时。
/// </summary>
/// <param name="manual">当为<see langword="true"/>时,意味着是调用<see cref="Close(string)"/>。当为<see langword="false"/>时,则是其他中断。</param>
/// <param name="msg"></param>
protected virtual void BreakOut(bool manual, string msg)
{
this.OnBreakOut?.Invoke(this, manual, msg);
}
/// <summary>
/// 释放对象
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!this.m_disposedValue)
{
if (disposing)
{
}
this.m_disposedValue = true;
}
UserToken.SafeDispose();
}
/// <summary>
/// 当发生异常的时候
/// </summary>
/// <param name="ex"></param>
protected virtual void Exception(Exception ex)
{
this.OnException?.Invoke(this, ex);
}
/// <summary>
/// 当收到数据的时候
/// </summary>
/// <param name="byteBlock"></param>
protected virtual void Received(ByteBlock byteBlock)
{
this.OnReceived?.Invoke(this, byteBlock);
}
private void HandleBuffer(ByteBlock byteBlock)
{
try
{
this.m_receiveCounter.Increment(byteBlock.Length);
this.Received(byteBlock);
}
catch (Exception ex)
{
this.Exception(ex);
}
finally
{
byteBlock.Dispose();
}
}
private void OnReceivePeriod(long value)
{
this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value);
}
private void OnSendPeriod(long value)
{
this.SendBufferSize = TouchSocketUtility.HitBufferLength(value);
}
private void PrivateBreakOut(bool manual, string msg)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.BreakOut(manual, msg);
}
}
}
private void ProcessReceived()
{
if (!this.m_online)
{
UserToken?.SafeDispose();
return;
}
if (MainSerialPort.BytesToRead > 0)
{
var byteBlock = UserToken;
byte[] buffer = BytePool.Default.Rent(MainSerialPort.BytesToRead);
int num = MainSerialPort.Read(buffer, 0, MainSerialPort.BytesToRead);
byteBlock.Write(buffer, 0, num);
byteBlock.SetLength(num);
this.HandleBuffer(byteBlock);
try
{
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
newByteBlock.SetLength(0);
UserToken = newByteBlock;
if (MainSerialPort.BytesToRead > 0)
{
this.m_bufferRate += 2;
this.ProcessReceived();
}
}
catch (Exception ex)
{
this.PrivateBreakOut(false, ex.Message);
}
}
}
}

View File

@@ -14,6 +14,7 @@ using System.IO.Ports;
namespace ThingsGateway.Foundation.Serial; namespace ThingsGateway.Foundation.Serial;
/// <inheritdoc cref="SerialSessionBase"/> /// <inheritdoc cref="SerialSessionBase"/>
public class SerialSession : SerialSessionBase public class SerialSession : SerialSessionBase
{ {
@@ -22,15 +23,18 @@ public class SerialSession : SerialSessionBase
/// </summary> /// </summary>
public ReceivedEventHandler<SerialSession> Received { get; set; } public ReceivedEventHandler<SerialSession> Received { get; set; }
/// <summary> /// <inheritdoc/>
/// 接收数据 protected override async Task ReceivedData(ReceivedDataEventArgs e)
/// </summary>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
this.Received?.Invoke(this, byteBlock, requestInfo); if (this.Received != null)
return false; {
await this.Received.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await base.ReceivedData(e);
} }
} }
@@ -46,33 +50,22 @@ public class SerialSessionBase : BaseSerial, ISerialSession
public SerialSessionBase() public SerialSessionBase()
{ {
this.Protocol = SerialPort; this.Protocol = SerialPort;
this.m_receiveCounter = new ValueCounter this.m_serialCore = new InternalSerialCore();
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnReceivePeriod
};
this.m_sendCounter = new ValueCounter
{
Period = TimeSpan.FromSeconds(1),
OnPeriod = this.OnSendPeriod
};
} }
#region #region
private DelaySender m_delaySender; private DelaySender m_delaySender;
private long m_bufferRate = 1;
private bool m_online => MainSerialPort?.IsOpen == true; private bool m_online => MainSerialPort?.IsOpen == true;
private ValueCounter m_receiveCounter; private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
private ValueCounter m_sendCounter; private readonly InternalSerialCore m_serialCore;
#endregion #endregion
#region #region
/// <inheritdoc/> /// <inheritdoc/>
public ConnectedEventHandler<ISerialSession> Connected { get; set; } public ConnectedEventHandler<ISerialSession> Connected { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public SerialConnectingEventHandler<ISerialSession> Connecting { get; set; } public SerialConnectingEventHandler<ISerialSession> Connecting { get; set; }
@@ -82,26 +75,28 @@ public class SerialSessionBase : BaseSerial, ISerialSession
/// <inheritdoc/> /// <inheritdoc/>
public DisconnectEventHandler<ISerialSessionBase> Disconnecting { get; set; } public DisconnectEventHandler<ISerialSessionBase> Disconnecting { get; set; }
private void PrivateOnConnected(object o) private Task PrivateOnConnected(object o)
{ {
var e = (ConnectedEventArgs)o; return this.OnConnected((ConnectedEventArgs)o);
this.OnConnected(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpConnectedPlugin.OnTcpConnected), this, e);
} }
/// <summary> /// <summary>
/// 已经建立Tcp连接 /// 已经建立连接
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnConnected(ConnectedEventArgs e) protected virtual async Task OnConnected(ConnectedEventArgs e)
{ {
try try
{ {
this.Connected?.Invoke(this, e); if (this.Connected != null)
{
await this.Connected.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpConnectedPlugin.OnTcpConnected), this, e);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -109,30 +104,33 @@ public class SerialSessionBase : BaseSerial, ISerialSession
} }
} }
private void PrivateOnConnecting(SerialConnectingEventArgs e) private Task PrivateOnConnecting(SerialConnectingEventArgs e)
{ {
if (this.CanSetDataHandlingAdapter) if (this.CanSetDataHandlingAdapter)
{ {
this.SetDataHandlingAdapter(this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty).Invoke()); this.SetDataHandlingAdapter(this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty).Invoke());
} }
this.OnConnecting(e); return this.OnConnecting(e);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpConnectingPlugin.OnTcpConnecting), this, e);
} }
/// <summary> /// <summary>
/// 准备连接的时候,此时已初始化Socket但是并未建立Tcp连接 /// 准备连接的时候,此时并未建立连接
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnConnecting(SerialConnectingEventArgs e) protected virtual async Task OnConnecting(SerialConnectingEventArgs e)
{ {
try try
{ {
this.Connecting?.Invoke(this, e); if (this.Connecting != null)
{
await this.Connecting.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpConnectingPlugin.OnTcpConnecting), this, e);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -140,25 +138,30 @@ public class SerialSessionBase : BaseSerial, ISerialSession
} }
} }
private void PrivateOnDisconnected(DisconnectEventArgs e) private Task PrivateOnDisconnected(object obj)
{ {
this.OnDisconnected(e); this.m_receiver?.TryInputReceive(default, default);
if (e.Handled) return this.OnDisconnected((DisconnectEventArgs)obj);
{
return;
}
this.PluginsManager.Raise(nameof(ITcpDisconnectedPlugin.OnTcpDisconnected), this, e);
} }
/// <summary> /// <summary>
/// 断开连接。在客户端未设置连接状态时,不会触发 /// 断开连接。在客户端未设置连接状态时,不会触发
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnDisconnected(DisconnectEventArgs e) protected virtual async Task OnDisconnected(DisconnectEventArgs e)
{ {
try try
{ {
this.Disconnected?.Invoke(this, e); if (this.Disconnected != null)
{
await this.Disconnected.Invoke(this, e).ConfigureAwait(false);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpDisconnectedPlugin.OnTcpDisconnected), this, e).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -166,28 +169,29 @@ public class SerialSessionBase : BaseSerial, ISerialSession
} }
} }
private void PrivateOnDisconnecting(DisconnectEventArgs e) private Task PrivateOnDisconnecting(object obj)
{ {
this.OnDisconnecting(e); return this.OnDisconnecting((DisconnectEventArgs)obj);
if (e.Handled)
{
return;
}
this.PluginsManager.Raise(nameof(ITcpDisconnectingPlugin.OnTcpDisconnecting), this, e);
} }
/// <summary> /// <summary>
/// 即将断开连接(仅主动断开时有效)。 /// 即将断开连接(仅主动断开时有效)。
/// <para>
/// 当主动调用Close断开时。
/// </para>
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnDisconnecting(DisconnectEventArgs e) protected virtual async Task OnDisconnecting(DisconnectEventArgs e)
{ {
try try
{ {
this.Disconnecting?.Invoke(this, e); if (this.Disconnecting != null)
{
await this.Disconnecting.Invoke(this, e).ConfigureAwait(false);
if (e.Handled)
{
return;
}
}
await this.PluginsManager.RaiseAsync(nameof(ITcpDisconnectingPlugin.OnTcpDisconnecting), this, e).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -200,16 +204,10 @@ public class SerialSessionBase : BaseSerial, ISerialSession
#region #region
/// <inheritdoc/> /// <inheritdoc/>
public DateTime LastReceivedTime => this.m_receiveCounter.LastIncrement; public DateTime LastReceivedTime => this.GetTcpCore().ReceiveCounter.LastIncrement;
/// <inheritdoc/> /// <inheritdoc/>
public DateTime LastSendTime => this.m_sendCounter.LastIncrement; public DateTime LastSendTime => this.GetTcpCore().SendCounter.LastIncrement;
/// <inheritdoc/>
public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
/// <inheritdoc/>
public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public IContainer Container { get; private set; } public IContainer Container { get; private set; }
@@ -223,10 +221,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
/// <inheritdoc/> /// <inheritdoc/>
public SingleStreamDataHandlingAdapter DataHandlingAdapter { get; private set; } public SingleStreamDataHandlingAdapter DataHandlingAdapter { get; private set; }
/// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary>
public SerialProperty SerialProperty { get; private set; } public SerialProperty SerialProperty { get; private set; }
/// <inheritdoc/> /// <inheritdoc/>
public SerialPort MainSerialPort { get; private set; } public SerialPort MainSerialPort { get; private set; }
@@ -241,9 +236,6 @@ public class SerialSessionBase : BaseSerial, ISerialSession
public IPluginsManager PluginsManager { get; private set; } public IPluginsManager PluginsManager { get; private set; }
/// <inheritdoc/>
public ReceiveType ReceiveType { get; private set; }
/// <inheritdoc/> /// <inheritdoc/>
public Protocol Protocol { get; set; } public Protocol Protocol { get; set; }
@@ -261,32 +253,13 @@ public class SerialSessionBase : BaseSerial, ISerialSession
{ {
if (this.m_online) if (this.m_online)
{ {
this.PrivateOnDisconnecting(new DisconnectEventArgs(true, msg)); Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, msg));
this.MainSerialPort.TryClose(); this.MainSerialPort.TryClose();
this.BreakOut(default, true, msg);
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(true, msg));
} }
} }
} }
private void BreakOut(string msg)
{
lock (this.SyncRoot)
{
if (this.m_online)
{
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(false, msg));
}
}
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
@@ -298,15 +271,8 @@ public class SerialSessionBase : BaseSerial, ISerialSession
{ {
if (this.m_online) if (this.m_online)
{ {
Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
this.MainSerialPort.TryClose(); this.BreakOut(default, true, $"{nameof(Dispose)}主动断开");
this.PrivateOnDisconnecting(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
this.PluginsManager.SafeDispose();
this.PrivateOnDisconnected(new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
} }
} }
base.Dispose(disposing); base.Dispose(disposing);
@@ -315,6 +281,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
#endregion #endregion
#region Connect #region Connect
/// <summary> /// <summary>
/// 打开串口 /// 打开串口
/// </summary> /// </summary>
@@ -332,25 +299,32 @@ public class SerialSessionBase : BaseSerial, ISerialSession
} }
if (this.Config == null) if (this.Config == null)
{ {
throw new ArgumentNullException("配置文件不能为空。"); throw new ArgumentNullException(nameof(this.Config), "配置文件不能为空。");
} }
var serialProperty = this.Config.GetValue(SerialConfigExtension.SerialProperty) ?? throw new ArgumentNullException("串口配置不能为空。"); var serialProperty = this.Config.GetValue(SerialConfigExtension.SerialProperty) ?? throw new ArgumentNullException("串口配置不能为空。");
this.MainSerialPort.SafeDispose(); this.MainSerialPort.SafeDispose();
var serialPort = CreateSerial(serialProperty); var serialPort = CreateSerial(serialProperty);
var args = new SerialConnectingEventArgs(this.MainSerialPort); this.PrivateOnConnecting(new(serialPort))
this.PrivateOnConnecting(args); .ConfigureAwait(false)
.GetAwaiter()
.GetResult();
serialPort.Open(); serialPort.Open();
this.SetSerialPort(serialPort); this.SetSerialPort(serialPort);
this.BeginReceive(); this.BeginReceive();
this.PrivateOnConnected(new ConnectedEventArgs());
Task.Factory.StartNew(this.PrivateOnConnected, new ConnectedEventArgs());
} }
} }
private void BeginReceive()
{
this.GetTcpCore().BeginIocpReceive();
}
/// <inheritdoc/> /// <inheritdoc/>
public virtual ISerialSession Connect() public virtual ISerialSession Connect()
{ {
@@ -366,43 +340,66 @@ public class SerialSessionBase : BaseSerial, ISerialSession
return this.Connect(); return this.Connect();
}); });
} }
#endregion Connect
#region Receiver
private Receiver m_receiver;
/// <inheritdoc/>
public IReceiver CreateReceiver()
{
return this.m_receiver ??= new Receiver(this);
}
/// <inheritdoc/>
public void ClearReceiver()
{
this.m_receiver = null;
}
#endregion #endregion
private void OnReceivePeriod(long value) private void BreakOut(SerialCore core, bool manual, string msg)
{ {
this.ReceiveBufferSize = TouchSocketUtility.HitBufferLength(value); lock (this.SyncRoot)
{
if (this.m_online)
{
this.MainSerialPort.SafeDispose();
this.m_delaySender.SafeDispose();
this.DataHandlingAdapter.SafeDispose();
Task.Factory.StartNew(this.PrivateOnDisconnected, new DisconnectEventArgs(manual, msg));
}
}
} }
private void OnSendPeriod(long value) private SerialCore GetTcpCore()
{ {
this.SendBufferSize = TouchSocketUtility.HitBufferLength(value); this.ThrowIfDisposed();
return this.m_serialCore ?? throw new ObjectDisposedException(this.GetType().Name);
} }
/// <inheritdoc/> /// <inheritdoc/>
public override int ReceiveBufferSize public override int ReceiveBufferSize
{ {
get => base.ReceiveBufferSize; get => this.GetTcpCore().ReceiveBufferSize;
set set
{ {
base.ReceiveBufferSize = value; this.GetTcpCore().ReceiveBufferSize = value;
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.ReadBufferSize = base.ReceiveBufferSize;
}
} }
} }
/// <inheritdoc/> /// <inheritdoc/>
public override int SendBufferSize public override int SendBufferSize
{ {
get => base.SendBufferSize; get => this.GetTcpCore().SendBufferSize;
set set
{ {
base.SendBufferSize = value; this.GetTcpCore().SendBufferSize = value;
if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
{
this.MainSerialPort.WriteBufferSize = base.SendBufferSize;
}
} }
} }
@@ -480,32 +477,24 @@ public class SerialSessionBase : BaseSerial, ISerialSession
private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
if (this.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false) if (this.m_receiver != null)
{ {
return; if (this.m_receiver.TryInputReceive(byteBlock, requestInfo))
} {
return;
if (this.HandleReceivedData(byteBlock, requestInfo)) }
{
return;
}
if (this.PluginsManager.Enable)
{
var args = new ReceivedDataEventArgs(byteBlock, requestInfo);
this.PluginsManager.Raise(nameof(ITcpReceivedPlugin.OnTcpReceived), this, args);
} }
this.ReceivedData(new ReceivedDataEventArgs(byteBlock, requestInfo)).GetFalseAwaitResult();
} }
/// <summary> /// <summary>
/// 处理已接收到的数据。 /// 当收到适配器处理的数据
/// </summary> /// </summary>
/// <param name="byteBlock">以二进制流形式传递</param> /// <param name="e"></param>
/// <param name="requestInfo">以解析的数据对象传递</param>
/// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns> /// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns>
protected virtual bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) protected virtual Task ReceivedData(ReceivedDataEventArgs e)
{ {
return false; return this.PluginsManager.RaiseAsync(nameof(ITcpReceivedPlugin.OnTcpReceived), this, e);
} }
/// <summary> /// <summary>
@@ -515,12 +504,12 @@ public class SerialSessionBase : BaseSerial, ISerialSession
/// <param name="offset">偏移</param> /// <param name="offset">偏移</param>
/// <param name="length">长度</param> /// <param name="length">长度</param>
/// <returns>返回值表示是否允许发送</returns> /// <returns>返回值表示是否允许发送</returns>
protected virtual bool HandleSendingData(byte[] buffer, int offset, int length) protected virtual async Task<bool> SendingData(byte[] buffer, int offset, int length)
{ {
if (this.PluginsManager.Enable) if (this.PluginsManager.GetPluginCount(nameof(ITcpSendingPlugin.OnTcpSending)) > 0)
{ {
var args = new SendingEventArgs(buffer, offset, length); var args = new SendingEventArgs(buffer, offset, length);
this.PluginsManager.Raise(nameof(ITcpSendingPlugin.OnTcpSending), this, args); await this.PluginsManager.RaiseAsync(nameof(ITcpSendingPlugin.OnTcpSending), this, args).ConfigureAwait(false);
return args.IsPermitOperation; return args.IsPermitOperation;
} }
return true; return true;
@@ -534,16 +523,6 @@ public class SerialSessionBase : BaseSerial, ISerialSession
{ {
this.SerialProperty = config.GetValue(SerialConfigExtension.SerialProperty); this.SerialProperty = config.GetValue(SerialConfigExtension.SerialProperty);
this.Logger ??= this.Container.Resolve<ILog>(); this.Logger ??= this.Container.Resolve<ILog>();
this.ReceiveType = config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty);
}
/// <summary>
/// 在延迟发生错误
/// </summary>
/// <param name="ex"></param>
protected virtual void OnDelaySenderError(Exception ex)
{
this.Logger.Log(LogLevel.Error, this, "发送错误", ex);
} }
/// <summary> /// <summary>
@@ -567,33 +546,10 @@ public class SerialSessionBase : BaseSerial, ISerialSession
adapter.OnLoaded(this); adapter.OnLoaded(this);
adapter.ReceivedCallBack = this.PrivateHandleReceivedData; adapter.ReceivedCallBack = this.PrivateHandleReceivedData;
adapter.SendCallBack = this.DefaultSend; adapter.SendCallBack = this.DefaultSend;
adapter.SendAsyncCallBack = this.DefaultSendAsync;
this.DataHandlingAdapter = adapter; this.DataHandlingAdapter = adapter;
} }
private void BeginReceive()
{
if (this.ReceiveType == ReceiveType.Iocp)
{
SerialReceivedEventArgs eventArgs = new();
var byteBlock = BytePool.Default.GetByteBlock(this.ReceiveBufferSize);
byteBlock.SetLength(0);
eventArgs.UserToken = byteBlock;
if (this.MainSerialPort.BytesToRead > 0)
{
this.ProcessReceived(eventArgs);
}
MainSerialPort.DataReceived += this.EventArgs_Completed;
}
else if (this.ReceiveType == ReceiveType.Bio)
{
new Thread(this.BeginBio)
{
IsBackground = true
}
.Start();
}
}
private static SerialPort CreateSerial(SerialProperty serialProperty) private static SerialPort CreateSerial(SerialProperty serialProperty)
{ {
SerialPort serialPort = new(serialProperty.PortName, serialProperty.BaudRate, serialProperty.Parity, serialProperty.DataBits, serialProperty.StopBits) SerialPort serialPort = new(serialProperty.PortName, serialProperty.BaudRate, serialProperty.Parity, serialProperty.DataBits, serialProperty.StopBits)
@@ -604,88 +560,6 @@ public class SerialSessionBase : BaseSerial, ISerialSession
return serialPort; return serialPort;
} }
private void EventArgs_Completed(object sender, SerialDataReceivedEventArgs e)
{
try
{
this.m_bufferRate = 1;
SerialReceivedEventArgs eventArgs = new();
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
newByteBlock.SetLength(0);
eventArgs.UserToken = newByteBlock;
if (MainSerialPort.BytesToRead > 0)
{
this.ProcessReceived(eventArgs);
}
}
catch (Exception ex)
{
this.BreakOut(ex.Message);
}
}
private void BeginBio()
{
while (true)
{
var byteBlock = new ByteBlock(this.ReceiveBufferSize);
try
{
int r = MainSerialPort.Read(byteBlock.Buffer, 0, MainSerialPort.BytesToRead);
if (r == 0)
{
this.BreakOut("远程终端主动关闭");
return;
}
byteBlock.SetLength(r);
this.HandleBuffer(byteBlock);
}
catch (Exception ex)
{
this.BreakOut(ex.Message);
return;
}
}
}
/// <summary>
/// 处理数据
/// </summary>
private void HandleBuffer(ByteBlock byteBlock)
{
try
{
this.m_receiveCounter.Increment(byteBlock.Length);
if (this.OnHandleRawBuffer?.Invoke(byteBlock) == false)
{
return;
}
if (this.DisposedValue)
{
return;
}
if (this.PluginsManager.Enable && this.PluginsManager.Raise(nameof(ITcpReceivingPlugin.OnTcpReceiving), this, new ByteBlockEventArgs(byteBlock)))
{
return;
}
if (this.DataHandlingAdapter == null)
{
this.Logger.Error(this, TouchSocketResource.NullDataAdapter.GetDescription());
return;
}
this.DataHandlingAdapter.ReceivedInput(byteBlock);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, "在处理数据时发生错误", ex);
}
finally
{
byteBlock.Dispose();
}
}
#region #region
#region #region
@@ -757,12 +631,14 @@ public class SerialSessionBase : BaseSerial, ISerialSession
{ {
length += item.Count; length += item.Count;
} }
using var byteBlock = new ByteBlock(length); using (var byteBlock = new ByteBlock(length))
foreach (var item in transferBytes)
{ {
byteBlock.Write(item.Array, item.Offset, item.Count); foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
this.DataHandlingAdapter.SendInput(byteBlock.Buffer, 0, byteBlock.Len);
} }
this.DataHandlingAdapter.SendInput(byteBlock.Buffer, 0, byteBlock.Len);
} }
} }
@@ -773,18 +649,20 @@ public class SerialSessionBase : BaseSerial, ISerialSession
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="buffer"><inheritdoc/></param> /// <param name="buffer"></param>
/// <param name="offset"><inheritdoc/></param> /// <param name="offset"></param>
/// <param name="length"><inheritdoc/></param> /// <param name="length"></param>
/// <exception cref="NotConnectedException"><inheritdoc/></exception> /// <exception cref="NotConnectedException"></exception>
/// <exception cref="OverlengthException"><inheritdoc/></exception> /// <exception cref="OverlengthException"></exception>
/// <exception cref="Exception"><inheritdoc/></exception> /// <exception cref="Exception"></exception>
public virtual Task SendAsync(byte[] buffer, int offset, int length) public virtual Task SendAsync(byte[] buffer, int offset, int length)
{ {
return Task.Run(() => this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{ {
this.Send(buffer, offset, length); throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}); }
return this.DataHandlingAdapter.SendInputAsync(buffer, offset, length);
} }
/// <summary> /// <summary>
@@ -796,118 +674,78 @@ public class SerialSessionBase : BaseSerial, ISerialSession
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public virtual Task SendAsync(IRequestInfo requestInfo) public virtual Task SendAsync(IRequestInfo requestInfo)
{ {
return Task.Run(() => this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{ {
this.Send(requestInfo); throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}); }
if (!this.DataHandlingAdapter.CanSendRequestInfo)
{
throw new NotSupportedException($"当前适配器不支持对象发送。");
}
return this.DataHandlingAdapter.SendInputAsync(requestInfo);
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="transferBytes"><inheritdoc/></param> /// <param name="transferBytes"></param>
/// <exception cref="NotConnectedException"><inheritdoc/></exception> /// <returns></returns>
/// <exception cref="OverlengthException"><inheritdoc/></exception> /// <exception cref="ArgumentNullException"></exception>
/// <exception cref="Exception"><inheritdoc/></exception>
public virtual Task SendAsync(IList<ArraySegment<byte>> transferBytes) public virtual Task SendAsync(IList<ArraySegment<byte>> transferBytes)
{ {
return Task.Run(() => this.ThrowIfDisposed();
if (this.DataHandlingAdapter == null)
{ {
this.Send(transferBytes); throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketResource.NullDataAdapter.GetDescription());
}); }
if (this.DataHandlingAdapter.CanSplicingSend)
{
return this.DataHandlingAdapter.SendInputAsync(transferBytes);
}
else
{
var length = 0;
foreach (var item in transferBytes)
{
length += item.Count;
}
using (var byteBlock = new ByteBlock(length))
{
foreach (var item in transferBytes)
{
byteBlock.Write(item.Array, item.Offset, item.Count);
}
return this.DataHandlingAdapter.SendInputAsync(byteBlock.Buffer, 0, byteBlock.Len);
}
}
} }
#endregion #endregion
/// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary>
/// <param name="buffer"><inheritdoc/></param>
/// <param name="offset"><inheritdoc/></param>
/// <param name="length"><inheritdoc/></param>
/// <exception cref="NotConnectedException"><inheritdoc/></exception>
/// <exception cref="OverlengthException"><inheritdoc/></exception>
/// <exception cref="Exception"><inheritdoc/></exception>
public void DefaultSend(byte[] buffer, int offset, int length) public void DefaultSend(byte[] buffer, int offset, int length)
{ {
if (!this.m_online) if (this.SendingData(buffer, offset, length).GetFalseAwaitResult())
{ {
throw new NotConnectedException(TouchSocketResource.NotConnected.GetDescription()); this.GetTcpCore().Send(buffer, offset, length);
}
if (this.HandleSendingData(buffer, offset, length))
{
if (this.m_delaySender != null && length < this.m_delaySender.DelayLength)
{
this.m_delaySender.Send(QueueDataBytes.CreateNew(buffer, offset, length));
}
else
{
this.MainSerialPort.AbsoluteSend(buffer, offset, length);
}
this.m_sendCounter.Increment(length);
} }
} }
/// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> public async Task DefaultSendAsync(byte[] buffer, int offset, int length)
/// <param name="buffer"><inheritdoc/></param>
/// <param name="offset"><inheritdoc/></param>
/// <param name="length"><inheritdoc/></param>
/// <exception cref="NotConnectedException"><inheritdoc/></exception>
/// <exception cref="OverlengthException"><inheritdoc/></exception>
/// <exception cref="Exception"><inheritdoc/></exception>
public Task DefaultSendAsync(byte[] buffer, int offset, int length)
{ {
return Task.Run(() => if (await this.SendingData(buffer, offset, length))
{ {
this.DefaultSend(buffer, offset, length); await this.GetTcpCore().SendAsync(buffer, offset, length);
}); }
} }
#endregion #endregion
private void ProcessReceived(SerialReceivedEventArgs e) #region
{
if (!this.m_online)
{
e.UserToken.SafeDispose();
return;
}
if (MainSerialPort.BytesToRead > 0)
{
byte[] buffer = new byte[2048];
var byteBlock = (ByteBlock)e.UserToken;
int num = MainSerialPort.Read(buffer, 0, MainSerialPort.BytesToRead);
byteBlock.Write(buffer, 0, num);
byteBlock.SetLength(num);
this.HandleBuffer(byteBlock);
try
{
var newByteBlock = BytePool.Default.GetByteBlock((int)Math.Min(this.ReceiveBufferSize * this.m_bufferRate, TouchSocketUtility.MaxBufferLength));
newByteBlock.SetLength(0);
e.UserToken = newByteBlock;
if (MainSerialPort.BytesToRead > 0)
{
this.m_bufferRate += 2;
this.ProcessReceived(e);
}
}
catch (Exception ex)
{
e.UserToken.SafeDispose();
this.BreakOut(ex.Message);
}
}
else
{
e.UserToken.SafeDispose();
this.BreakOut("远程终端主动关闭");
}
}
private void SetSerialPort(SerialPort serialPort) private void SetSerialPort(SerialPort serialPort)
{ {
@@ -917,15 +755,63 @@ public class SerialSessionBase : BaseSerial, ISerialSession
} }
this.MainSerialPort = serialPort; this.MainSerialPort = serialPort;
this.SerialProperty ??= new();
this.SerialProperty.Parity = serialPort.Parity;
this.SerialProperty.PortName = serialPort.PortName;
this.SerialProperty.StopBits = serialPort.StopBits;
this.SerialProperty.DataBits = serialPort.DataBits;
this.SerialProperty.BaudRate = serialPort.BaudRate;
var delaySenderOption = this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty); var delaySenderOption = this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty);
if (delaySenderOption != null) if (delaySenderOption != null)
{ {
this.m_delaySender = new DelaySender(delaySenderOption, this.MainSerialPort.AbsoluteSend); this.m_delaySender = new DelaySender(delaySenderOption, this.MainSerialPort.AbsoluteSend);
} }
this.m_serialCore.Reset(serialPort);
this.m_serialCore.OnReceived = this.HandleReceived;
this.m_serialCore.OnBreakOut = this.BreakOut;
} }
/// <inheritdoc/>
public override string ToString() private void HandleReceived(SerialCore core, ByteBlock byteBlock)
{ {
return SerialProperty?.ToString(); try
{
if (this.DisposedValue)
{
return;
}
if (this.ReceivingData(byteBlock).GetFalseAwaitResult())
{
return;
}
if (this.DataHandlingAdapter == null)
{
this.Logger.Error(this, TouchSocketResource.NullDataAdapter.GetDescription());
return;
}
this.DataHandlingAdapter.ReceivedInput(byteBlock);
}
catch (Exception ex)
{
this.Logger.Log(LogLevel.Error, this, "在处理数据时发生错误", ex);
}
} }
/// <summary>
/// 当收到原始数据
/// </summary>
/// <param name="byteBlock"></param>
/// <returns>如果返回<see langword="true"/>则表示数据已被处理,且不会再向下传递。</returns>
protected virtual Task<bool> ReceivingData(ByteBlock byteBlock)
{
if (this.PluginsManager.GetPluginCount(nameof(ITcpReceivingPlugin.OnTcpReceiving)) > 0)
{
return this.PluginsManager.RaiseAsync(nameof(ITcpReceivingPlugin.OnTcpReceiving), this, new ByteBlockEventArgs(byteBlock));
}
return Task.FromResult(false);
}
#endregion
} }

View File

@@ -34,21 +34,24 @@ namespace ThingsGateway.Foundation.Sockets
/// 同步根。 /// 同步根。
/// </summary> /// </summary>
protected readonly object SyncRoot = new object(); protected readonly object SyncRoot = new object();
private int m_receiveBufferSize = 1024 * 64;
private int m_sendBufferSize = 1024 * 64; private int m_receiveBufferSize = 1024 * 10;
private int m_sendBufferSize = 1024 * 10;
/// <inheritdoc/> /// <inheritdoc/>
public virtual int SendBufferSize public virtual int SendBufferSize
{ {
get => m_sendBufferSize; get => this.m_sendBufferSize;
set => m_sendBufferSize = value < 1024 ? 1024 : value; set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual int ReceiveBufferSize public virtual int ReceiveBufferSize
{ {
get => m_receiveBufferSize; get => this.m_receiveBufferSize;
set => m_receiveBufferSize = value < 1024 ? 1024 : value; set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
} }
/// <inheritdoc/> /// <inheritdoc/>
public ILog Logger { get; set; } public ILog Logger { get; set; }
} }

View File

@@ -32,11 +32,6 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
public int SendTimeout { get; set; } public int SendTimeout { get; set; }
/// <summary>
/// 接收类型
/// </summary>
public ReceiveType ReceiveType { get; set; } = ReceiveType.Iocp;
/// <summary> /// <summary>
/// 是否使用地址复用 /// 是否使用地址复用
/// </summary> /// </summary>

View File

@@ -44,23 +44,22 @@ namespace ThingsGateway.Foundation.Sockets
/// 在NAT服务器收到数据时。 /// 在NAT服务器收到数据时。
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="byteBlock"></param> /// <param name="e"></param>
/// <param name="requestInfo"></param>
/// <returns>需要转发的数据。</returns> /// <returns>需要转发的数据。</returns>
protected virtual byte[] OnNATReceived(NATSocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo) protected virtual byte[] OnNATReceived(NATSocketClient socketClient, ReceivedDataEventArgs e)
{ {
return byteBlock?.ToArray(); return e.ByteBlock?.ToArray();
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="byteBlock"></param> /// <param name="e"></param>
/// <param name="requestInfo"></param> protected override sealed async Task OnReceived(NATSocketClient socketClient, ReceivedDataEventArgs e)
protected override sealed void OnReceived(NATSocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
var data = this.OnNATReceived(socketClient, byteBlock, requestInfo); await EasyTask.CompletedTask;
var data = this.OnNATReceived(socketClient, e);
if (data != null) if (data != null)
{ {
socketClient.SendToTargetClient(data, 0, data.Length); socketClient.SendToTargetClient(data, 0, data.Length);
@@ -82,12 +81,11 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="tcpClient"></param> /// <param name="tcpClient"></param>
/// <param name="byteBlock"></param> /// <param name="e"></param>
/// <param name="requestInfo"></param>
/// <returns></returns> /// <returns></returns>
protected virtual byte[] OnTargetClientReceived(NATSocketClient socketClient, ITcpClient tcpClient, ByteBlock byteBlock, IRequestInfo requestInfo) protected virtual byte[] OnTargetClientReceived(NATSocketClient socketClient, ITcpClient tcpClient, ReceivedDataEventArgs e)
{ {
return byteBlock?.ToArray(); return e.ByteBlock?.ToArray();
} }
} }
} }

View File

@@ -31,7 +31,7 @@ namespace ThingsGateway.Foundation.Sockets
public class NATSocketClient : SocketClient public class NATSocketClient : SocketClient
{ {
internal Action<NATSocketClient, ITcpClient, DisconnectEventArgs> m_internalDis; internal Action<NATSocketClient, ITcpClient, DisconnectEventArgs> m_internalDis;
internal Func<NATSocketClient, ITcpClient, ByteBlock, IRequestInfo, byte[]> m_internalTargetClientRev; internal Func<NATSocketClient, ITcpClient, ReceivedDataEventArgs, byte[]> m_internalTargetClientRev;
private readonly ConcurrentList<ITcpClient> m_targetClients = new ConcurrentList<ITcpClient>(); private readonly ConcurrentList<ITcpClient> m_targetClients = new ConcurrentList<ITcpClient>();
/// <summary> /// <summary>
@@ -100,18 +100,19 @@ namespace ThingsGateway.Foundation.Sockets
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnDisconnected(DisconnectEventArgs e) protected override async Task OnDisconnected(DisconnectEventArgs e)
{ {
foreach (var client in this.m_targetClients) foreach (var client in this.m_targetClients)
{ {
client.TryShutdown(); client.TryShutdown();
client.SafeDispose(); client.SafeDispose();
} }
base.OnDisconnected(e); await base.OnDisconnected(e);
} }
private void TcpClient_Disconnected(ITcpClientBase client, DisconnectEventArgs e) private async Task TcpClient_Disconnected(ITcpClientBase client, DisconnectEventArgs e)
{ {
await EasyTask.CompletedTask;
foreach (var item in client.PluginsManager.Plugins) foreach (var item in client.PluginsManager.Plugins)
{ {
if (typeof(ReconnectionPlugin<>) == item.GetType().GetGenericTypeDefinition()) if (typeof(ReconnectionPlugin<>) == item.GetType().GetGenericTypeDefinition())
@@ -125,8 +126,9 @@ namespace ThingsGateway.Foundation.Sockets
this.m_internalDis?.Invoke(this, (ITcpClient)client, e); this.m_internalDis?.Invoke(this, (ITcpClient)client, e);
} }
private void TcpClient_Received(TcpClient client, ByteBlock byteBlock, IRequestInfo requestInfo) private async Task TcpClient_Received(TcpClient client, ReceivedDataEventArgs e)
{ {
await EasyTask.CompletedTask;
if (this.DisposedValue) if (this.DisposedValue)
{ {
return; return;
@@ -134,7 +136,7 @@ namespace ThingsGateway.Foundation.Sockets
try try
{ {
var data = this.m_internalTargetClientRev?.Invoke(this, client, byteBlock, requestInfo); var data = this.m_internalTargetClientRev?.Invoke(this, client, e);
if (data != null) if (data != null)
{ {
if (this.CanSend) if (this.CanSend)

View File

@@ -27,11 +27,10 @@ using System.Net.Sockets;
namespace ThingsGateway.Foundation.Sockets namespace ThingsGateway.Foundation.Sockets
{ {
/// <summary> /// <summary>
/// TCP泛型服务器,由使用者自己指定<see cref="SocketClient"/>类型。 /// Tcp泛型服务器,由使用者自己指定<see cref="SocketClient"/>类型。
/// </summary> /// </summary>
public class TcpService<TClient> : TcpServiceBase, ITcpService<TClient> where TClient : SocketClient, new() public class TcpService<TClient> : TcpServiceBase, ITcpService<TClient> where TClient : SocketClient, new()
{ {
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
@@ -102,25 +101,17 @@ namespace ThingsGateway.Foundation.Sockets
/// <summary> /// <summary>
/// 即将断开连接(仅主动断开时有效)。 /// 即将断开连接(仅主动断开时有效)。
/// <para>
/// 当主动调用Close断开时可通过<see cref="MsgPermitEventArgs.IsPermitOperation"/>终止断开行为。
/// </para>
/// </summary> /// </summary>
public DisconnectEventHandler<TClient> Disconnecting { get; set; } public DisconnectEventHandler<TClient> Disconnecting { get; set; }
/// <summary>
/// 当客户端Id被修改时触发。
/// </summary>
public IdChangedEventHandler<TClient> IdChanged { get; set; }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected override sealed void OnClientConnected(ISocketClient socketClient, ConnectedEventArgs e) protected override sealed Task OnClientConnected(ISocketClient socketClient, ConnectedEventArgs e)
{ {
this.OnConnected((TClient)socketClient, e); return this.OnConnected((TClient)socketClient, e);
} }
/// <summary> /// <summary>
@@ -128,9 +119,9 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected override sealed void OnClientConnecting(ISocketClient socketClient, ConnectingEventArgs e) protected override sealed Task OnClientConnecting(ISocketClient socketClient, ConnectingEventArgs e)
{ {
this.OnConnecting((TClient)socketClient, e); return this.OnConnecting((TClient)socketClient, e);
} }
/// <summary> /// <summary>
@@ -138,9 +129,9 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected override sealed void OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e) protected override sealed Task OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e)
{ {
this.OnDisconnected((TClient)socketClient, e); return this.OnDisconnected((TClient)socketClient, e);
} }
/// <summary> /// <summary>
@@ -148,20 +139,19 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected override sealed void OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e) protected override sealed Task OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e)
{ {
this.OnDisconnecting((TClient)socketClient, e); return this.OnDisconnecting((TClient)socketClient, e);
} }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="byteBlock"></param> /// <param name="e"></param>
/// <param name="requestInfo"></param> protected override sealed Task OnClientReceivedData(ISocketClient socketClient, ReceivedDataEventArgs e)
protected override sealed void OnClientReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
this.OnReceived((TClient)socketClient, byteBlock, requestInfo); return this.OnReceived((TClient)socketClient, e);
} }
/// <summary> /// <summary>
@@ -169,9 +159,13 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnConnected(TClient socketClient, ConnectedEventArgs e) protected virtual Task OnConnected(TClient socketClient, ConnectedEventArgs e)
{ {
this.Connected?.Invoke(socketClient, e); if (this.Connected != null)
{
return this.Connected.Invoke(socketClient, e);
}
return EasyTask.CompletedTask;
} }
/// <summary> /// <summary>
@@ -179,9 +173,13 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnConnecting(TClient socketClient, ConnectingEventArgs e) protected virtual Task OnConnecting(TClient socketClient, ConnectingEventArgs e)
{ {
this.Connecting?.Invoke(socketClient, e); if (this.Connecting != null)
{
return this.Connecting.Invoke(socketClient, e);
}
return EasyTask.CompletedTask;
} }
/// <summary> /// <summary>
@@ -189,32 +187,37 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnDisconnected(TClient socketClient, DisconnectEventArgs e) protected virtual Task OnDisconnected(TClient socketClient, DisconnectEventArgs e)
{ {
this.Disconnected?.Invoke(socketClient, e); if (this.Disconnected != null)
{
return this.Disconnected.Invoke(socketClient, e);
}
return EasyTask.CompletedTask;
} }
/// <summary> /// <summary>
/// 即将断开连接(仅主动断开时有效)。 /// 即将断开连接(仅主动断开时有效)。
/// <para>
/// 当主动调用Close断开时可通过<see cref="MsgPermitEventArgs.IsPermitOperation"/>终止断开行为。
/// </para>
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnDisconnecting(TClient socketClient, DisconnectEventArgs e) protected virtual Task OnDisconnecting(TClient socketClient, DisconnectEventArgs e)
{ {
this.Disconnecting?.Invoke(socketClient, e); if (this.Disconnected != null)
{
return this.Disconnecting.Invoke(socketClient, e);
}
return EasyTask.CompletedTask;
} }
/// <summary> /// <summary>
/// 当收到适配器数据。 /// 当收到适配器数据。
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="byteBlock"></param> /// <param name="e"></param>
/// <param name="requestInfo"></param> protected virtual Task OnReceived(TClient socketClient, ReceivedDataEventArgs e)
protected virtual void OnReceived(TClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
return EasyTask.CompletedTask;
} }
#endregion #endregion
@@ -224,7 +227,6 @@ namespace ThingsGateway.Foundation.Sockets
return Interlocked.Increment(ref this.m_nextId).ToString(); return Interlocked.Increment(ref this.m_nextId).ToString();
} }
/// <summary> /// <summary>
/// 获取下一个新Id /// 获取下一个新Id
/// </summary> /// </summary>
@@ -363,7 +365,6 @@ namespace ThingsGateway.Foundation.Sockets
/// <inheritdoc/> /// <inheritdoc/>
public override IService Setup(TouchSocketConfig config) public override IService Setup(TouchSocketConfig config)
{ {
if (config == null) if (config == null)
{ {
throw new ArgumentNullException(nameof(config)); throw new ArgumentNullException(nameof(config));
@@ -434,7 +435,6 @@ namespace ThingsGateway.Foundation.Sockets
ReuseAddress = this.Config.GetValue(TouchSocketConfigExtension.ReuseAddressProperty), ReuseAddress = this.Config.GetValue(TouchSocketConfigExtension.ReuseAddressProperty),
NoDelay = this.Config.GetValue(TouchSocketConfigExtension.NoDelayProperty), NoDelay = this.Config.GetValue(TouchSocketConfigExtension.NoDelayProperty),
Adapter = this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty), Adapter = this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty),
ReceiveType = this.Config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty)
}; };
option.Backlog = this.Config.GetValue(TouchSocketConfigExtension.BacklogProperty) ?? option.Backlog; option.Backlog = this.Config.GetValue(TouchSocketConfigExtension.BacklogProperty) ?? option.Backlog;
option.SendTimeout = this.Config.GetValue(TouchSocketConfigExtension.SendTimeoutProperty); option.SendTimeout = this.Config.GetValue(TouchSocketConfigExtension.SendTimeoutProperty);
@@ -540,11 +540,11 @@ namespace ThingsGateway.Foundation.Sockets
this.Clear(); this.Clear();
this.m_serverState = ServerState.Disposed; this.m_serverState = ServerState.Disposed;
if (this.PluginsManager?.Enable == true) if (this.PluginsManager.Enable)
{ {
this.m_pluginsManager.Raise(nameof(IServerStopedPlugin.OnServerStoped), this, new ServiceStateEventArgs(this.m_serverState, default)); this.m_pluginsManager.Raise(nameof(IServerStopedPlugin.OnServerStoped), this, new ServiceStateEventArgs(this.m_serverState, default));
} }
this.PluginsManager?.SafeDispose(); this.PluginsManager.SafeDispose();
} }
base.Dispose(disposing); base.Dispose(disposing);
} }
@@ -691,7 +691,7 @@ namespace ThingsGateway.Foundation.Sockets
return new NormalDataHandlingAdapter(); return new NormalDataHandlingAdapter();
} }
private void OnClientSocketInit(object obj) private async Task OnClientSocketInit(object obj)
{ {
var tuple = (Tuple<Socket, TcpNetworkMonitor>)obj; var tuple = (Tuple<Socket, TcpNetworkMonitor>)obj;
var socket = tuple.Item1; var socket = tuple.Item1;
@@ -717,30 +717,35 @@ namespace ThingsGateway.Foundation.Sockets
{ {
client.SetDataHandlingAdapter(this.GetAdapter(monitor)); client.SetDataHandlingAdapter(this.GetAdapter(monitor));
} }
client.InternalInitialized();
await client.InternalInitialized();
var args = new ConnectingEventArgs(socket) var args = new ConnectingEventArgs(socket)
{ {
Id = this.GetNextNewId() Id = this.GetNextNewId()
}; };
client.InternalConnecting(args);//Connecting await client.InternalConnecting(args);//Connecting
if (args.IsPermitOperation) if (args.IsPermitOperation)
{ {
client.InternalSetId(args.Id); client.InternalSetId(args.Id);
if (!client.MainSocket.Connected) if (!socket.Connected)
{ {
client.MainSocket.SafeDispose(); socket.SafeDispose();
return; return;
} }
if (this.m_socketClients.TryAdd(client)) if (this.m_socketClients.TryAdd(client))
{ {
client.InternalConnected(new ConnectedEventArgs()); _ = client.InternalConnected(new ConnectedEventArgs());
if (!socket.Connected)
{
return;
}
if (monitor.Option.UseSsl) if (monitor.Option.UseSsl)
{ {
try try
{ {
client.BeginReceiveSsl(monitor.Option.ServiceSslOption); await client.AuthenticateAsync(monitor.Option.ServiceSslOption);
_ = client.BeginReceiveSsl();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -772,7 +777,7 @@ namespace ThingsGateway.Foundation.Sockets
} }
/// <summary> /// <summary>
/// TCP服务器 /// Tcp服务器
/// </summary> /// </summary>
public class TcpService : TcpService<SocketClient> public class TcpService : TcpService<SocketClient>
{ {
@@ -781,16 +786,14 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
public ReceivedEventHandler<SocketClient> Received { get; set; } public ReceivedEventHandler<SocketClient> Received { get; set; }
/// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> protected override Task OnReceived(SocketClient socketClient, ReceivedDataEventArgs e)
/// <param name="socketClient"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override void OnReceived(SocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
this.Received?.Invoke(socketClient, byteBlock, requestInfo); if (this.Received != null)
base.OnReceived(socketClient, byteBlock, requestInfo); {
return this.Received.Invoke(socketClient, e);
}
return EasyTask.CompletedTask;
} }
} }
} }

View File

@@ -22,6 +22,7 @@
// 感谢您的下载和使用 // 感谢您的下载和使用
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System.Collections.Concurrent;
namespace ThingsGateway.Foundation.Sockets namespace ThingsGateway.Foundation.Sockets
{ {
@@ -122,29 +123,64 @@ namespace ThingsGateway.Foundation.Sockets
/// <returns></returns> /// <returns></returns>
public abstract IService Stop(); public abstract IService Stop();
internal void OnInternalConnected(ISocketClient socketClient, ConnectedEventArgs e) private ConcurrentStack<TcpCore> m_tcpCores = new ConcurrentStack<TcpCore>();
/// <summary>
/// 租用TcpCore
/// </summary>
/// <returns></returns>
public TcpCore RentTcpCore()
{ {
this.OnClientConnected(socketClient, e); if (this.m_tcpCores.TryPop(out var tcpCore))
{
return tcpCore;
}
return new InternalTcpCore();
} }
internal void OnInternalConnecting(ISocketClient socketClient, ConnectingEventArgs e) /// <inheritdoc/>
protected override void Dispose(bool disposing)
{ {
this.OnClientConnecting(socketClient, e); while (this.m_tcpCores.TryPop(out var tcpCore))
{
tcpCore.SafeDispose();
}
base.Dispose(disposing);
} }
internal void OnInternalDisconnected(ISocketClient socketClient, DisconnectEventArgs e) /// <summary>
/// 归还TcpCore
/// </summary>
/// <param name="tcpCore"></param>
public void ReturnTcpCore(TcpCore tcpCore)
{ {
this.OnClientDisconnected(socketClient, e); this.m_tcpCores.Push(tcpCore);
} }
internal void OnInternalDisconnecting(ISocketClient socketClient, DisconnectEventArgs e) internal Task OnInternalConnected(ISocketClient socketClient, ConnectedEventArgs e)
{ {
this.OnClientDisconnecting(socketClient, e); return this.OnClientConnected(socketClient, e);
} }
internal void OnInternalReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo) internal Task OnInternalConnecting(ISocketClient socketClient, ConnectingEventArgs e)
{ {
this.OnClientReceivedData(socketClient, byteBlock, requestInfo); return this.OnClientConnecting(socketClient, e);
}
internal Task OnInternalDisconnected(ISocketClient socketClient, DisconnectEventArgs e)
{
return this.OnClientDisconnected(socketClient, e);
}
internal Task OnInternalDisconnecting(ISocketClient socketClient, DisconnectEventArgs e)
{
return this.OnClientDisconnecting(socketClient, e);
}
internal Task OnInternalReceivedData(ISocketClient socketClient, ReceivedDataEventArgs e)
{
return this.OnClientReceivedData(socketClient, e);
} }
/// <summary> /// <summary>
@@ -152,39 +188,35 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected abstract void OnClientConnected(ISocketClient socketClient, ConnectedEventArgs e); protected abstract Task OnClientConnected(ISocketClient socketClient, ConnectedEventArgs e);
/// <summary> /// <summary>
/// 客户端请求连接 /// 客户端请求连接
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected abstract void OnClientConnecting(ISocketClient socketClient, ConnectingEventArgs e); protected abstract Task OnClientConnecting(ISocketClient socketClient, ConnectingEventArgs e);
/// <summary> /// <summary>
/// 客户端断开连接 /// 客户端断开连接
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected abstract void OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e); protected abstract Task OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e);
/// <summary> /// <summary>
/// 即将断开连接(仅主动断开时有效)。 /// 即将断开连接(仅主动断开时有效)。
/// <para>
/// 当主动调用Close断开时可通过<see cref="MsgPermitEventArgs.IsPermitOperation"/>终止断开行为。
/// </para>
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="e"></param> /// <param name="e"></param>
protected abstract void OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e); protected abstract Task OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e);
/// <summary> /// <summary>
/// 收到数据时 /// 收到数据时
/// </summary> /// </summary>
/// <param name="socketClient"></param> /// <param name="socketClient"></param>
/// <param name="byteBlock"></param> /// <param name="e"></param>
/// <param name="requestInfo"></param> protected abstract Task OnClientReceivedData(ISocketClient socketClient, ReceivedDataEventArgs e);
protected abstract void OnClientReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo);
#region Id发送 #region Id发送

View File

@@ -36,17 +36,20 @@ namespace ThingsGateway.Foundation.Sockets
/// <summary> /// <summary>
/// 当收到数据时 /// 当收到数据时
/// </summary> /// </summary>
public UdpReceivedEventHandler Received { get; set; } public UdpReceivedEventHandler<UdpSession> Received { get; set; }
/// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> protected override async Task ReceivedData(UdpReceivedDataEventArgs e)
/// <param name="remoteEndPoint"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
this.Received?.Invoke(remoteEndPoint, byteBlock, requestInfo); if (this.Received != null)
{
await this.Received.Invoke(this, e);
if (e.Handled)
{
return;
}
}
await base.ReceivedData(e);
} }
} }
@@ -70,16 +73,6 @@ namespace ThingsGateway.Foundation.Sockets
this.SendBufferSize = 1024 * 64; this.SendBufferSize = 1024 * 64;
} }
/// <summary>
/// 处理未经过适配器的数据。返回值表示是否继续向下传递。
/// </summary>
public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
/// <summary>
/// 处理经过适配器后的数据。返回值表示是否继续向下传递。
/// </summary>
public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
@@ -342,7 +335,6 @@ namespace ThingsGateway.Foundation.Sockets
this.PluginsManager.Raise(nameof(IServerStartedPlugin.OnServerStarted), this, new ServiceStateEventArgs(this.ServerState, ex) { Message = ex.Message }); this.PluginsManager.Raise(nameof(IServerStartedPlugin.OnServerStarted), this, new ServiceStateEventArgs(this.ServerState, ex) { Message = ex.Message });
throw; throw;
} }
} }
/// <summary> /// <summary>
@@ -391,11 +383,9 @@ namespace ThingsGateway.Foundation.Sockets
/// <summary> /// <summary>
/// 处理已接收到的数据。 /// 处理已接收到的数据。
/// </summary> /// </summary>
/// <param name="remoteEndPoint"></param> protected virtual Task ReceivedData(UdpReceivedDataEventArgs e)
/// <param name="byteBlock">以二进制流形式传递</param>
/// <param name="requestInfo">以解析的数据对象传递</param>
protected virtual void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
return this.PluginsManager.RaiseAsync(nameof(IUdpReceivedPlugin.OnUdpReceived), this, e);
} }
/// <summary> /// <summary>
@@ -492,7 +482,7 @@ namespace ThingsGateway.Foundation.Sockets
} }
#endif #endif
#endregion #endregion Windows下UDP连接被重置错误10054
this.PreviewBind(socket); this.PreviewBind(socket);
@@ -500,55 +490,48 @@ namespace ThingsGateway.Foundation.Sockets
this.Monitor = new UdpNetworkMonitor(iPHost, socket); this.Monitor = new UdpNetworkMonitor(iPHost, socket);
switch (this.Config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty))
#if NET45_OR_GREATER || NET6_0_OR_GREATER
for (var i = 0; i < threadCount; i++)
{ {
case ReceiveType.Iocp: var eventArg = new SocketAsyncEventArgs();
{ this.m_socketAsyncs.Add(eventArg);
#if NET45_OR_GREATER||NET6_0_OR_GREATER eventArg.Completed += this.IO_Completed;
for (var i = 0; i < threadCount; i++) var byteBlock = new ByteBlock(this.ReceiveBufferSize);
{ eventArg.UserToken = byteBlock;
var eventArg = new SocketAsyncEventArgs(); eventArg.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
this.m_socketAsyncs.Add(eventArg); eventArg.RemoteEndPoint = iPHost.EndPoint;
eventArg.Completed += this.IO_Completed; if (!socket.ReceiveFromAsync(eventArg))
var byteBlock = new ByteBlock(this.ReceiveBufferSize); {
eventArg.UserToken = byteBlock; this.ProcessReceive(socket, eventArg);
eventArg.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity); }
eventArg.RemoteEndPoint = iPHost.EndPoint;
if (!socket.ReceiveFromAsync(eventArg))
{
this.ProcessReceive(socket, eventArg);
}
}
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
for (var i = 0; i < threadCount; i++)
{
var eventArg = new SocketAsyncEventArgs();
this.m_socketAsyncs.Add(eventArg);
eventArg.Completed += this.IO_Completed;
var byteBlock = new ByteBlock(this.ReceiveBufferSize);
eventArg.UserToken = byteBlock;
eventArg.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
eventArg.RemoteEndPoint = iPHost.EndPoint;
if (!socket.ReceiveFromAsync(eventArg))
{
this.ProcessReceive(socket, eventArg);
}
}
}
else
{
var thread = new Thread(this.Received);
thread.IsBackground = true;
thread.Start();
}
#endif
break;
}
default:
throw new Exception("UDP中只支持Auto模式");
} }
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
for (var i = 0; i < threadCount; i++)
{
var eventArg = new SocketAsyncEventArgs();
this.m_socketAsyncs.Add(eventArg);
eventArg.Completed += this.IO_Completed;
var byteBlock = new ByteBlock(this.ReceiveBufferSize);
eventArg.UserToken = byteBlock;
eventArg.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
eventArg.RemoteEndPoint = iPHost.EndPoint;
if (!socket.ReceiveFromAsync(eventArg))
{
this.ProcessReceive(socket, eventArg);
}
}
}
else
{
var thread = new Thread(this.Received);
thread.IsBackground = true;
thread.Start();
}
#endif
} }
private void Received() private void Received()
@@ -577,10 +560,6 @@ namespace ThingsGateway.Foundation.Sockets
try try
{ {
this.LastReceivedTime = DateTime.Now; this.LastReceivedTime = DateTime.Now;
if (this.OnHandleRawBuffer?.Invoke(byteBlock) == false)
{
return;
}
if (this.DisposedValue) if (this.DisposedValue)
{ {
return; return;
@@ -609,21 +588,14 @@ namespace ThingsGateway.Foundation.Sockets
private void PrivateHandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo) private void PrivateHandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
{ {
if (this.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false) if (this.m_receiver != null)
{ {
return; if (this.m_receiver.TryInputReceive(byteBlock, requestInfo))
}
if (this.PluginsManager.Enable)
{
var args = new UdpReceivedDataEventArgs(remoteEndPoint, byteBlock, requestInfo);
this.PluginsManager.Raise(nameof(IUdpReceivedPlugin.OnUdpReceived), this, args);
if (args.Handled)
{ {
return; return;
} }
} }
this.HandleReceivedData(remoteEndPoint, byteBlock, requestInfo); this.ReceivedData(new UdpReceivedDataEventArgs(remoteEndPoint, byteBlock, requestInfo)).GetFalseAwaitResult();
} }
#region #region
@@ -663,7 +635,7 @@ namespace ThingsGateway.Foundation.Sockets
{ {
throw new NotSupportedException($"当前适配器不支持对象发送。"); throw new NotSupportedException($"当前适配器不支持对象发送。");
} }
this.DataHandlingAdapter.SendInput(requestInfo); //this.DataHandlingAdapter.SendInput(requestInfo);
} }
#endregion #endregion
@@ -682,9 +654,9 @@ namespace ThingsGateway.Foundation.Sockets
public virtual Task SendAsync(byte[] buffer, int offset, int length) public virtual Task SendAsync(byte[] buffer, int offset, int length)
{ {
return Task.Run(() => return Task.Run(() =>
{ {
this.Send(buffer, offset, length); this.Send(buffer, offset, length);
}); });
} }
/// <summary> /// <summary>
@@ -737,9 +709,9 @@ namespace ThingsGateway.Foundation.Sockets
public virtual Task SendAsync(EndPoint remoteEP, byte[] buffer, int offset, int length) public virtual Task SendAsync(EndPoint remoteEP, byte[] buffer, int offset, int length)
{ {
return Task.Run(() => return Task.Run(() =>
{ {
this.Send(remoteEP, buffer, offset, length); this.Send(remoteEP, buffer, offset, length);
}); });
} }
#endregion #endregion
@@ -906,5 +878,23 @@ namespace ThingsGateway.Foundation.Sockets
} }
#endregion #endregion
#region Receiver
private Receiver m_receiver;
/// <inheritdoc/>
public IReceiver CreateReceiver()
{
return this.m_receiver ??= new Receiver(this);
}
/// <inheritdoc/>
public void ClearReceiver()
{
this.m_receiver = null;
}
#endregion
} }
} }

View File

@@ -91,15 +91,6 @@ namespace ThingsGateway.Foundation.Sockets
} }
} }
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="requestInfo"></param>
protected override void PreviewSend(IRequestInfo requestInfo)
{
throw new System.NotImplementedException();
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>

View File

@@ -365,15 +365,6 @@ namespace ThingsGateway.Foundation.Sockets
} }
} }
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="requestInfo"></param>
protected override void PreviewSend(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>

View File

@@ -22,67 +22,57 @@
// 感谢您的下载和使用 // 感谢您的下载和使用
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System.Net;
/// <summary> namespace ThingsGateway.Foundation.Sockets
/// 显示信息 {
/// </summary> /// <summary>
/// <param name="client"></param> /// Connected
/// <param name="e"></param> /// </summary>
public delegate void MessageEventHandler<TClient>(TClient client, MsgPermitEventArgs e); /// <typeparam name="TClient"></typeparam>
/// <param name="client"></param>
/// <param name="e"></param>
public delegate Task ConnectedEventHandler<TClient>(TClient client, ConnectedEventArgs e);
/// <summary> /// <summary>
/// 普通通知 /// Connecting
/// </summary> /// </summary>
/// <typeparam name="TClient"></typeparam> /// <typeparam name="TClient"></typeparam>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="e"></param> /// <param name="e"></param>
public delegate void TouchSocketEventHandler<TClient>(TClient client, PluginEventArgs e); public delegate Task ConnectingEventHandler<TClient>(TClient client, ConnectingEventArgs e);
/// <summary> /// <summary>
/// Id修改通知 /// 客户端断开连接
/// </summary> /// </summary>
/// <typeparam name="TClient"></typeparam> /// <typeparam name="TClient"></typeparam>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="e"></param> /// <param name="e"></param>
public delegate void IdChangedEventHandler<TClient>(TClient client, IdChangedEventArgs e); public delegate Task DisconnectEventHandler<TClient>(TClient client, DisconnectEventArgs e);
/// <summary> /// <summary>
/// Connecting /// 显示信息
/// </summary> /// </summary>
/// <typeparam name="TClient"></typeparam> /// <param name="client"></param>
/// <param name="client"></param> /// <param name="e"></param>
/// <param name="e"></param> public delegate void MessageEventHandler<TClient>(TClient client, MsgPermitEventArgs e);
public delegate void ConnectingEventHandler<TClient>(TClient client, ConnectingEventArgs e);
/// <summary> /// <summary>
/// Connected /// 接收数据
/// </summary> /// </summary>
/// <typeparam name="TClient"></typeparam> /// <param name="client"></param>
/// <param name="client"></param> /// <param name="e"></param>
/// <param name="e"></param> public delegate Task ReceivedEventHandler<TClient>(TClient client, ReceivedDataEventArgs e);
public delegate void ConnectedEventHandler<TClient>(TClient client, ConnectedEventArgs e);
/// <summary> /// <summary>
/// 客户端断开连接 /// 普通通知
/// </summary> /// </summary>
/// <typeparam name="TClient"></typeparam> /// <typeparam name="TClient"></typeparam>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="e"></param> /// <param name="e"></param>
public delegate void DisconnectEventHandler<TClient>(TClient client, DisconnectEventArgs e); public delegate void TouchSocketEventHandler<TClient>(TClient client, PluginEventArgs e);
/// <summary> /// <summary>
/// 接收数据 /// Udp接收
/// </summary> /// </summary>
/// <param name="client"></param> public delegate Task UdpReceivedEventHandler<TClient>(TClient client, UdpReceivedDataEventArgs e);
/// <param name="byteBlock"></param> }
/// <param name="requestInfo"></param>
public delegate void ReceivedEventHandler<TClient>(TClient client, ByteBlock byteBlock, IRequestInfo requestInfo);
/// <summary>
/// UDP接收
/// </summary>
/// <param name="endpoint"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
public delegate void UdpReceivedEventHandler(EndPoint endpoint, ByteBlock byteBlock, IRequestInfo requestInfo);

View File

@@ -1,48 +0,0 @@
#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace ThingsGateway.Foundation.Sockets
{
/// <summary>
/// 接收类型
/// </summary>
public enum ReceiveType : byte
{
/// <summary>
/// 在该模式下,不会投递接收申请,用户可通过<see cref="ITcpClientBase.GetStream"/>,获取到流以后,自己处理接收。
/// <para>注意:连接端不会感知主动断开</para>
/// </summary>
None,
/// <summary>
/// 该模式下会使用Iocp自动接收数据然后主动触发。
/// </summary>
Iocp,
/// <summary>
/// 该模式下,会使用同步阻塞模式接收数据。注意:使用该模式时,每个回话连接会独占一个线程。
/// </summary>
Bio
}
}

View File

@@ -122,18 +122,39 @@ namespace ThingsGateway.Foundation.Sockets
/// <inheritdoc cref="ITcpClient.Connect(int)"/> /// <inheritdoc cref="ITcpClient.Connect(int)"/>
public static TClient Connect<TClient>(this TClient client, string ipHost, int timeout = 5000) where TClient : ITcpClient public static TClient Connect<TClient>(this TClient client, string ipHost, int timeout = 5000) where TClient : ITcpClient
{ {
client.Setup(ipHost); TouchSocketConfig config;
if (client.Config == null)
{
config = new TouchSocketConfig();
config.SetRemoteIPHost(ipHost);
client.Setup(config);
}
else
{
config = client.Config;
config.SetRemoteIPHost(ipHost);
}
client.Connect(timeout); client.Connect(timeout);
return client; return client;
} }
/// <inheritdoc cref="ITcpClient.ConnectAsync(int)"/> /// <inheritdoc cref="ITcpClient.ConnectAsync(int)"/>
public static Task<TClient> ConnectAsync<TClient>(this TClient client, string ipHost, int timeout = 5000) where TClient : ITcpClient public static async Task<TClient> ConnectAsync<TClient>(this TClient client, string ipHost, int timeout = 5000) where TClient : ITcpClient
{ {
return Task.Run(() => TouchSocketConfig config;
if (client.Config == null)
{ {
return Connect(client, ipHost, timeout); config = new TouchSocketConfig();
}); config.SetRemoteIPHost(ipHost);
client.Setup(config);
}
else
{
config = client.Config;
config.SetRemoteIPHost(ipHost);
}
await client.ConnectAsync(timeout);
return client;
} }
/// <summary> /// <summary>

View File

@@ -22,8 +22,18 @@ namespace ThingsGateway.Foundation.Sockets
/// <inheritdoc cref="IService.Start"/> /// <inheritdoc cref="IService.Start"/>
public static TService Start<TService>(this TService service, params IPHost[] iPHosts) where TService : ITcpService public static TService Start<TService>(this TService service, params IPHost[] iPHosts) where TService : ITcpService
{ {
service.Setup(new TouchSocketConfig() TouchSocketConfig config;
.SetListenIPHosts(iPHosts)); if (service.Config == null)
{
config = new TouchSocketConfig();
config.SetListenIPHosts(iPHosts);
service.Setup(config);
}
else
{
config = service.Config;
config.SetListenIPHosts(iPHosts);
}
service.Start(); service.Start();
return service; return service;
} }
@@ -35,8 +45,18 @@ namespace ThingsGateway.Foundation.Sockets
/// <inheritdoc cref="IService.Start"/> /// <inheritdoc cref="IService.Start"/>
public static TService Start<TService>(this TService service, IPHost iPHost) where TService : IUdpSession public static TService Start<TService>(this TService service, IPHost iPHost) where TService : IUdpSession
{ {
service.Setup(new TouchSocketConfig() TouchSocketConfig config;
.SetBindIPHost(iPHost)); if (service.Config == null)
{
config = new TouchSocketConfig();
config.SetBindIPHost(iPHost);
service.Setup(config);
}
else
{
config = service.Config;
config.SetBindIPHost(iPHost);
}
service.Start(); service.Start();
return service; return service;
} }

View File

@@ -44,14 +44,6 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
public static readonly DependencyProperty<Func<SingleStreamDataHandlingAdapter>> TcpDataHandlingAdapterProperty = DependencyProperty<Func<SingleStreamDataHandlingAdapter>>.Register("TcpDataHandlingAdapter", () => { return new NormalDataHandlingAdapter(); }); public static readonly DependencyProperty<Func<SingleStreamDataHandlingAdapter>> TcpDataHandlingAdapterProperty = DependencyProperty<Func<SingleStreamDataHandlingAdapter>>.Register("TcpDataHandlingAdapter", () => { return new NormalDataHandlingAdapter(); });
/// <summary>
/// 接收类型,默认为<see cref="ReceiveType.Iocp"/>
/// <para><see cref="ReceiveType.Iocp"/>为自动接收数据,然后主动触发。</para>
/// <para><see cref="ReceiveType.None"/>为不投递IO接收申请用户可通过<see cref="ITcpClientBase.GetStream"/>,获取到流以后,自己处理接收。注意:连接端不会感知主动断开</para>
/// 所需类型<see cref="ThingsGateway.Foundation.Sockets. ReceiveType"/>
/// </summary>
public static readonly DependencyProperty<ReceiveType> ReceiveTypeProperty = DependencyProperty<ReceiveType>.Register("ReceiveType", ReceiveType.Iocp);
/// <summary> /// <summary>
/// 数据处理适配器,默认为获取<see cref="UdpDataHandlingAdapter"/> /// 数据处理适配器,默认为获取<see cref="UdpDataHandlingAdapter"/>
/// 所需类型<see cref="Func{TResult}"/> /// 所需类型<see cref="Func{TResult}"/>
@@ -83,20 +75,6 @@ namespace ThingsGateway.Foundation.Sockets
return config; return config;
} }
/// <summary>
/// 接收类型,默认为<see cref="ReceiveType.Iocp"/>
/// <para><see cref="ReceiveType.Iocp"/>为自动接收数据,然后主动触发。</para>
/// <para><see cref="ReceiveType.None"/>为不投递IO接收申请用户可通过<see cref="ITcpClientBase.GetStream"/>,获取到流以后,自己处理接收。注意:连接端不会感知主动断开</para>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static TouchSocketConfig SetReceiveType(this TouchSocketConfig config, ReceiveType value)
{
config.SetValue(ReceiveTypeProperty, value);
return config;
}
/// <summary> /// <summary>
/// 设置(Udp系)数据处理适配器。 /// 设置(Udp系)数据处理适配器。
/// </summary> /// </summary>

View File

@@ -30,16 +30,16 @@ namespace ThingsGateway.Foundation.Sockets
/// </summary> /// </summary>
public interface IClient : IDependencyObject, IDisposable, ISocket public interface IClient : IDependencyObject, IDisposable, ISocket
{ {
/// <summary>
/// 获取一个同步数据接收器
/// </summary>
/// <returns></returns>
IReceiver CreateReceiver();
/// <summary> /// <summary>
/// 处理未经过适配器的数据。返回值表示是否继续向下传递。 /// 移除同步数据接收器
/// </summary> /// </summary>
Func<ByteBlock, bool> OnHandleRawBuffer { get; set; } void ClearReceiver();
/// <summary>
/// 处理经过适配器后的数据。返回值表示是否继续向下传递。
/// </summary>
Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
/// <summary> /// <summary>
/// 终端协议 /// 终端协议

View File

@@ -22,7 +22,6 @@
// 感谢您的下载和使用 // 感谢您的下载和使用
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System.Net.Sockets;
namespace ThingsGateway.Foundation.Sockets namespace ThingsGateway.Foundation.Sockets
{ {
@@ -46,8 +45,6 @@ namespace ThingsGateway.Foundation.Sockets
/// <summary> /// <summary>
/// 异步发送数据。 /// 异步发送数据。
/// <para>在<see cref="ITcpClient"/>时,如果使用独立线程发送,则不会触发异常。</para>
/// <para>在<see cref="ITcpClientBase"/>时,相当于<see cref="Socket.BeginSend(byte[], int, int, SocketFlags, out SocketError, System.AsyncCallback, object)"/>。</para>
/// <para>该发送会经过适配器封装,具体封装内容由适配器决定。</para> /// <para>该发送会经过适配器封装,具体封装内容由适配器决定。</para>
/// </summary> /// </summary>
/// <param name="buffer">数据缓存区</param> /// <param name="buffer">数据缓存区</param>

Some files were not shown because too many files have changed in this diff Show More