update touchsocket
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
			
		||||
<Project>
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<Version>3.0.0.7</Version>
 | 
			
		||||
		<Version>3.0.0.8</Version>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
		<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
		<Authors>Diego</Authors>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<Project>
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<Version>3.0.0.7</Version>
 | 
			
		||||
		<Version>3.0.0.8</Version>
 | 
			
		||||
		<GenerateDocumentationFile>True</GenerateDocumentationFile>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
@@ -42,5 +42,9 @@
 | 
			
		||||
		</None>
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup Condition="'$(Configuration)' == 'Release'">
 | 
			
		||||
		<DebugSymbols>True</DebugSymbols>
 | 
			
		||||
		<DebugType>Embedded</DebugType>
 | 
			
		||||
		<EmbedAllSources>True</EmbedAllSources>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
 | 
			
		||||
 | 
			
		||||
internal static class PackHelper
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
@@ -24,7 +24,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, OperResult> WriteData;
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, Task<OperResult>> WriteData;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 继电器
 | 
			
		||||
@@ -267,12 +267,13 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
    {
 | 
			
		||||
        return Task.FromResult(Write(address, value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void Received(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    protected override async Task Received(SerialSession client, ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            var requestInfo = e.RequestInfo;
 | 
			
		||||
            //接收外部报文
 | 
			
		||||
            if (requestInfo is ModbusSerialServerMessage modbusServerMessage)
 | 
			
		||||
            {
 | 
			
		||||
@@ -312,7 +313,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
                        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));
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
@@ -349,7 +350,7 @@ public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
 | 
			
		||||
                        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);
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
 
 | 
			
		||||
@@ -84,15 +84,6 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
            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/>
 | 
			
		||||
    public override void SetDataAdapter(object socketClient = null)
 | 
			
		||||
@@ -195,7 +186,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                var item = commandResult.Content;
 | 
			
		||||
                if (FrameTime != 0)
 | 
			
		||||
                    Thread.Sleep(FrameTime);
 | 
			
		||||
                var WaitingClientEx = client.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
                var WaitingClientEx = client.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
                var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
 | 
			
		||||
                return (MessageBase)result.RequestInfo;
 | 
			
		||||
            }
 | 
			
		||||
@@ -222,7 +213,7 @@ public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
 | 
			
		||||
 | 
			
		||||
                var item = commandResult.Content;
 | 
			
		||||
                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);
 | 
			
		||||
                return (MessageBase)result.RequestInfo;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, OperResult> WriteData;
 | 
			
		||||
    public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, Task<OperResult>> WriteData;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 继电器
 | 
			
		||||
@@ -284,12 +284,13 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
    {
 | 
			
		||||
        return Task.FromResult(Write(address, value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void Received(SocketClient client, IRequestInfo requestInfo)
 | 
			
		||||
    protected override async Task Received(SocketClient client, ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            var requestInfo = e.RequestInfo;
 | 
			
		||||
            //接收外部报文
 | 
			
		||||
            if (requestInfo is ModbusTcpServerMessage modbusServerMessage)
 | 
			
		||||
            {
 | 
			
		||||
@@ -330,7 +331,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                        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));
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
@@ -367,7 +368,7 @@ public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
 | 
			
		||||
                        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);
 | 
			
		||||
                                if (result.IsSuccess)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,8 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
	
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -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的滴答单位都是100ns(100纳秒,千万分之一秒),所以转换时只需要考虑开始时间即可
 | 
			
		||||
            </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>
 | 
			
		||||
@@ -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>
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.Siemens;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.Siemens;
 | 
			
		||||
 | 
			
		||||
internal static class PackHelper
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,6 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            tcpClient.Connected += Connected;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -293,8 +292,8 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override void SetDataAdapter(object socketClient = null)
 | 
			
		||||
        {
 | 
			
		||||
            SiemensS7PLCDataHandleAdapter DataHandleAdapter = new();
 | 
			
		||||
            TcpClient.SetDataHandlingAdapter(DataHandleAdapter);
 | 
			
		||||
            SiemensS7PLCDataHandleAdapter dataHandleAdapter = new();
 | 
			
		||||
            TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -476,17 +475,20 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        private void Connected(ITcpClient client, ConnectedEventArgs e)
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override async Task Connected(ITcpClient client, ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var result1 = SendThenResponse(ISO_CR);
 | 
			
		||||
                NormalDataHandlingAdapter dataHandleAdapter = new();
 | 
			
		||||
                TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
 | 
			
		||||
                var result1 = await SendThenResponseAsync(ISO_CR);
 | 
			
		||||
                if (!result1.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger?.Warning($"{client.IP} : {client.Port}:ISO_TP握手失败-{result1.Message}");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var result2 = SendThenResponse(S7_PN);
 | 
			
		||||
                var result2 = await SendThenResponseAsync(S7_PN);
 | 
			
		||||
                if (!result2.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger?.Warning($"{client.IP} : {client.Port}:PDU初始化失败-{result2.Message}");
 | 
			
		||||
@@ -499,7 +501,11 @@ namespace ThingsGateway.Foundation.Adapter.Siemens
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Exception(ex);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                SetDataAdapter();
 | 
			
		||||
            }
 | 
			
		||||
            await base.Connected(client, e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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>
 | 
			
		||||
@@ -24,7 +24,7 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    public ReadWriteDevicesSerialSessionBase(SerialSession serialSession)
 | 
			
		||||
    {
 | 
			
		||||
        SerialSession = serialSession;
 | 
			
		||||
        WaitingClientEx = SerialSession.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
        WaitingClientEx = SerialSession.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
        SerialSession.Received -= Received;
 | 
			
		||||
        SerialSession.Connecting -= Connecting;
 | 
			
		||||
        SerialSession.Connected -= Connected;
 | 
			
		||||
@@ -40,21 +40,15 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <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>
 | 
			
		||||
    /// 串口管理对象
 | 
			
		||||
@@ -102,8 +96,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { BreakTrigger = true, ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = SerialSession.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = SerialSession.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -117,8 +111,8 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = await SerialSession.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = await SerialSession.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -132,24 +126,34 @@ public abstract class ReadWriteDevicesSerialSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        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() + "连接成功");
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Connecting(ISerialSession client, SerialConnectingEventArgs e)
 | 
			
		||||
    private Task Connecting(ISerialSession client, SerialConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Disconnecting(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    private Task Disconnecting(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.SerialProperty.ToString() + "正在主动断开连接-" + e.Message);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,7 +23,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    public ReadWriteDevicesTcpClientBase(TcpClient tcpClient)
 | 
			
		||||
    {
 | 
			
		||||
        TcpClient = tcpClient;
 | 
			
		||||
        WaitingClientEx = TcpClient.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
        WaitingClientEx = TcpClient.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
        TcpClient.Connecting -= Connecting;
 | 
			
		||||
        TcpClient.Connected -= Connected;
 | 
			
		||||
        TcpClient.Disconnecting -= Disconnecting;
 | 
			
		||||
@@ -59,7 +59,7 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override Task ConnectAsync(CancellationToken cancellationToken)
 | 
			
		||||
    {
 | 
			
		||||
        return TcpClient.ConnectAsync(ConnectTimeOut);
 | 
			
		||||
        return TcpClient.ConnectAsync(ConnectTimeOut, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -86,8 +86,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { BreakTrigger = true, ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = TcpClient.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, };
 | 
			
		||||
            ResponsedData result = TcpClient.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -101,8 +101,8 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = await TcpClient.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = await TcpClient.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -116,24 +116,34 @@ public abstract class ReadWriteDevicesTcpClientBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        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() + "连接成功");
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Connecting(ITcpClient client, ConnectingEventArgs e)
 | 
			
		||||
    private Task Connecting(ITcpClient client, ConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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);
 | 
			
		||||
        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);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -77,57 +77,54 @@ public abstract class ReadWriteDevicesTcpServerBase : ReadWriteDevicesBase
 | 
			
		||||
        if (CascadeDisposal)
 | 
			
		||||
            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/>
 | 
			
		||||
    public override string ToString()
 | 
			
		||||
    {
 | 
			
		||||
        return TcpService.ServerName;
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收解析
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected virtual void Received(SocketClient client, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></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 + "连接成功");
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected virtual void Connecting(SocketClient client, ConnectingEventArgs e)
 | 
			
		||||
    protected virtual Task Connecting(SocketClient client, ConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
 | 
			
		||||
        SetDataAdapter(client);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <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);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <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);
 | 
			
		||||
        return EasyTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Received(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            Received(client, requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            Logger.Exception(this, ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,7 +22,7 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        UdpSession = udpSession;
 | 
			
		||||
        SetDataAdapter();
 | 
			
		||||
        WaitingClientEx = UdpSession.GetWaitingClientEx(new() { BreakTrigger = true });
 | 
			
		||||
        WaitingClientEx = UdpSession.GetWaitingClient(new() { ThrowBreakException = true });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -64,8 +64,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = UdpSession.GetWaitingClientEx(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = UdpSession.GetWaitingClient(waitingOptions).SendThenResponse(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -79,8 +79,8 @@ public abstract class ReadWriteDevicesUdpSessionBase : ReadWriteDevicesBase
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true, AdapterFilter = AdapterFilter.NoneAll };
 | 
			
		||||
            ResponsedData result = await UdpSession.GetWaitingClientEx(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            waitingOptions ??= new WaitingOptions { ThrowBreakException = true };
 | 
			
		||||
            ResponsedData result = await UdpSession.GetWaitingClient(waitingOptions).SendThenResponseAsync(data, TimeOut, cancellationToken);
 | 
			
		||||
            return OperResult.CreateSuccessResult(result.Data);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
 
 | 
			
		||||
@@ -143,6 +143,21 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
 | 
			
		||||
        GoSend(bytes, 0, bytes.Length);
 | 
			
		||||
        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/>
 | 
			
		||||
    protected override void PreviewSend(byte[] buffer, int offset, int length)
 | 
			
		||||
@@ -150,6 +165,12 @@ public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDat
 | 
			
		||||
        GoSend(buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override Task PreviewSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
    {
 | 
			
		||||
        return GoSendAsync(buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 报文拆包
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -128,11 +128,6 @@ public abstract class ReadWriteDevicesUdpDataHandleAdapter<TRequest> : UdpDataHa
 | 
			
		||||
    {
 | 
			
		||||
        throw new System.NotImplementedException();//因为设置了不支持拼接发送,所以该方法可以不实现。
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void PreviewSend(IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        throw new System.NotImplementedException();//因为设置了不支持,所以该方法可以不实现。
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override void Reset()
 | 
			
		||||
 
 | 
			
		||||
@@ -19,5 +19,20 @@
 | 
			
		||||
		<PackageReference Include="System.IO.Ports" Version="7.0.0" />
 | 
			
		||||
	</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>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// 具有释放的对象。
 | 
			
		||||
    /// 并未实现析构函数相关。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class DisposableObject : IDisposable
 | 
			
		||||
    public partial class DisposableObject : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 判断是否已释放。
 | 
			
		||||
 
 | 
			
		||||
@@ -69,14 +69,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.Owner = owner;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送数据的切入点,该方法由框架自动调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        public void SendInput(IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            this.PreviewSend(requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在解析时发生错误。
 | 
			
		||||
@@ -96,11 +88,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据前预先处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected abstract void PreviewSend(IRequestInfo requestInfo);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 重置解析器到初始状态,一般在<see cref="OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。
 | 
			
		||||
 
 | 
			
		||||
@@ -78,6 +78,24 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -242,6 +242,131 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -183,6 +183,70 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -240,5 +240,64 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                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();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,19 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
 | 
			
		||||
//  CSDN博客:https://blog.csdn.net/qq_40374647
 | 
			
		||||
//  哔哩哔哩视频:https://space.bilibili.com/94253567
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/RRQM_Home
 | 
			
		||||
//  Github源代码仓库:https://github.com/RRQM
 | 
			
		||||
//  API首页:http://rrqm_home.gitee.io/touchsocket/
 | 
			
		||||
//  交流QQ群:234762506
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -37,4 +50,4 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool? UpdateCacheTimeWhenRev { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -36,9 +36,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        public TimeSpan CacheTimeout { get; set; } = TimeSpan.FromSeconds(1);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否启用缓存超时。默认true。
 | 
			
		||||
        /// 是否启用缓存超时。默认false。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool CacheTimeoutEnable { get; set; } = true;
 | 
			
		||||
        public bool CacheTimeoutEnable { get; set; } = false;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当接收数据处理完成后,回调该函数执行接收
 | 
			
		||||
@@ -46,10 +46,15 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        public Action<ByteBlock, IRequestInfo> ReceivedCallBack { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当接收数据处理完成后,回调该函数执行发送
 | 
			
		||||
        /// 当发送数据处理完成后,回调该函数执行发送
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<byte[], int, int> SendCallBack { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当发送数据处理完成后,回调该函数执行异步发送
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<byte[], int, int, Task> SendAsyncCallBack { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否在收到数据时,即刷新缓存时间。默认true。
 | 
			
		||||
        /// <list type="number">
 | 
			
		||||
@@ -64,6 +69,12 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected DateTime LastCacheTime { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CanSendRequestInfo => false;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override bool CanSplicingSend => false;
 | 
			
		||||
 | 
			
		||||
        /// <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>
 | 
			
		||||
@@ -100,6 +122,98 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -130,27 +244,24 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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>
 | 
			
		||||
        /// 当接收到数据后预先处理数据,然后调用<see cref="GoReceived(ByteBlock, IRequestInfo)"/>处理数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        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>
 | 
			
		||||
        /// 重置解析器到初始状态,一般在<see cref="DataHandlingAdapter.OnError(string, bool, bool)"/>被触发时,由返回值指示是否调用。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -63,9 +63,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static SingleStreamDataAdapterTester CreateTester(SingleStreamDataHandlingAdapter adapter, int bufferLength = 1024, Action<ByteBlock, IRequestInfo> receivedCallBack = default)
 | 
			
		||||
        {
 | 
			
		||||
            var tester = new SingleStreamDataAdapterTester();
 | 
			
		||||
            tester.m_adapter = adapter;
 | 
			
		||||
            tester.m_bufferLength = bufferLength;
 | 
			
		||||
            var tester = new SingleStreamDataAdapterTester
 | 
			
		||||
            {
 | 
			
		||||
                m_adapter = adapter,
 | 
			
		||||
                m_bufferLength = bufferLength
 | 
			
		||||
            };
 | 
			
		||||
            adapter.SendCallBack = tester.SendCallback;
 | 
			
		||||
            adapter.ReceivedCallBack = tester.OnReceived;
 | 
			
		||||
            tester.m_receivedCallBack = receivedCallBack;
 | 
			
		||||
@@ -129,7 +131,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        {
 | 
			
		||||
            while (!this.m_dispose)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.tryGet(out var byteBlocks))
 | 
			
		||||
                if (this.TryGet(out var byteBlocks))
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var block in byteBlocks)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -163,7 +165,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            this.m_asyncBytes.Enqueue(asyncByte);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool tryGet(out List<ByteBlock> byteBlocks)
 | 
			
		||||
        private bool TryGet(out List<ByteBlock> byteBlocks)
 | 
			
		||||
        {
 | 
			
		||||
            byteBlocks = new List<ByteBlock>();
 | 
			
		||||
            ByteBlock block = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -70,10 +70,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public object Resolve(Type fromType, object[] ps = null, string key = "")
 | 
			
		||||
        public object Resolve(Type fromType, string key = "")
 | 
			
		||||
        {
 | 
			
		||||
            if (fromType == typeof(IContainer))
 | 
			
		||||
            {
 | 
			
		||||
@@ -108,11 +107,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                            {
 | 
			
		||||
                                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
 | 
			
		||||
                                {
 | 
			
		||||
                                    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)
 | 
			
		||||
                    {
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()), ps);
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType.MakeGenericType(fromType.GetGenericArguments()));
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType, ps);
 | 
			
		||||
                        return this.Create(descriptor, descriptor.ToType);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -143,10 +142,10 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                    }
 | 
			
		||||
                    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
 | 
			
		||||
            {
 | 
			
		||||
@@ -172,7 +171,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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));
 | 
			
		||||
            if (ctor is null)
 | 
			
		||||
@@ -198,28 +197,21 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            {
 | 
			
		||||
                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
 | 
			
		||||
                    {
 | 
			
		||||
                        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
 | 
			
		||||
                        {
 | 
			
		||||
                            if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
 | 
			
		||||
                            {
 | 
			
		||||
                                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);
 | 
			
		||||
                            }
 | 
			
		||||
                            ps[i] = this.Resolve(parameters[i].ParameterType, null);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -239,7 +231,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                        {
 | 
			
		||||
                            var attribute = item.GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                            var type = attribute.Type ?? item.PropertyType;
 | 
			
		||||
                            obj = this.Resolve(type, default, attribute.Key);
 | 
			
		||||
                            obj = this.Resolve(type, attribute.Key);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
@@ -259,28 +251,21 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                    ps = new object[parameters.Length];
 | 
			
		||||
                    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
 | 
			
		||||
                        {
 | 
			
		||||
                            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
 | 
			
		||||
                            {
 | 
			
		||||
                                if (parameters[i].IsDefined(typeof(DependencyInjectAttribute), true))
 | 
			
		||||
                                {
 | 
			
		||||
                                    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);
 | 
			
		||||
                                }
 | 
			
		||||
                                ps[i] = this.Resolve(parameters[i].ParameterType, null);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 
 | 
			
		||||
@@ -381,35 +381,11 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T"></typeparam>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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);
 | 
			
		||||
            return (T)container.Resolve(typeof(T), key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -461,7 +437,7 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
                            {
 | 
			
		||||
                                var attribute = parameters[i].GetCustomAttribute<DependencyInjectAttribute>();
 | 
			
		||||
                                var type = attribute.Type ?? parameters[i].ParameterType;
 | 
			
		||||
                                ps[i] = container.Resolve(type, default, attribute.Key);
 | 
			
		||||
                                ps[i] = container.Resolve(type, attribute.Key);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
@@ -489,47 +465,22 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
            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>
 | 
			
		||||
        ///  尝试创建类型对应的实例,如果类型没有注册,则会返回null或者默认值类型。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <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))
 | 
			
		||||
            {
 | 
			
		||||
                return container.Resolve(fromType, ps, key);
 | 
			
		||||
                return container.Resolve(fromType, key);
 | 
			
		||||
            }
 | 
			
		||||
            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>
 | 
			
		||||
        /// 尝试创建类型对应的实例,如果类型没有注册,则会返回null或者默认值类型。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -537,9 +488,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// <param name="container"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <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
 | 
			
		||||
 
 | 
			
		||||
@@ -34,10 +34,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// 创建目标类型的对应实例。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        object Resolve(Type fromType, object[] ps = null, string key = "");
 | 
			
		||||
        object Resolve(Type fromType, string key = "");
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 判断某类型是否已经注册
 | 
			
		||||
 
 | 
			
		||||
@@ -67,13 +67,13 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// <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")
 | 
			
		||||
            {
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.TryResolve(fromType, out var instance, ps, key))
 | 
			
		||||
            if (this.TryResolve(fromType, out var instance, key))
 | 
			
		||||
            {
 | 
			
		||||
                return instance;
 | 
			
		||||
            }
 | 
			
		||||
@@ -100,10 +100,9 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="fromType"></param>
 | 
			
		||||
        /// <param name="instance"></param>
 | 
			
		||||
        /// <param name="ps"></param>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <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())
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Core
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -29,5 +30,24 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    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();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -30,14 +30,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IPlugin : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 插件执行顺序
 | 
			
		||||
        /// <para>该属性值越大,越靠前执行。值相等时,按添加先后顺序</para>
 | 
			
		||||
        /// <para>该属性效果,仅在<see cref="IPluginsManager.Add(IPlugin)"/>之前设置有效。</para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [Obsolete("该属性已被弃用,插件顺序将直接由添加顺序决定。本设置将在正式版发布时直接删除", true)]
 | 
			
		||||
        int Order { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在插件被成功添加在<see cref="IPluginsManager"/>时执行。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,6 @@ namespace ThingsGateway.Foundation.Core
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class PluginBase : DisposableObject, IPlugin
 | 
			
		||||
    {
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        [Obsolete("该属性已被弃用,插件顺序将直接由添加顺序决定。本设置将在正式版发布时直接删除", true)]
 | 
			
		||||
        public int Order { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IPlugin.Loaded(IPluginsManager)"/>
 | 
			
		||||
        protected virtual void Loaded(IPluginsManager pluginsManager)
 | 
			
		||||
 
 | 
			
		||||
@@ -184,7 +184,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                }
 | 
			
		||||
                if (!this.Online)
 | 
			
		||||
                {
 | 
			
		||||
                    await base.ConnectAsync(timeout);
 | 
			
		||||
                    await base.ConnectAsync(timeout, token);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var request = new HttpRequest()
 | 
			
		||||
@@ -223,20 +223,20 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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.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/>
 | 
			
		||||
@@ -251,9 +251,9 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -62,10 +62,10 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnConnected(TClient socketClient, ConnectedEventArgs e)
 | 
			
		||||
        protected override async Task OnConnected(TClient socketClient, ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            socketClient.m_internalOnRpcActorInit = this.PrivateOnRpcActorInit;
 | 
			
		||||
            base.OnConnected(socketClient, e);
 | 
			
		||||
            await base.OnConnected(socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IDmtpActor OnServiceFindDmtpActor(string id)
 | 
			
		||||
 
 | 
			
		||||
@@ -96,42 +96,55 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///// <inheritdoc/>
 | 
			
		||||
        //protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        //{
 | 
			
		||||
        //    if (this.Protocol == DmtpUtility.DmtpProtocol && requestInfo is DmtpMessage message)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        if (!this.m_smtpActor.InputReceivedData(message))
 | 
			
		||||
        //        {
 | 
			
		||||
        //            if (this.PluginsManager.Enable)
 | 
			
		||||
        //            {
 | 
			
		||||
        //                this.PluginsManager.Raise(nameof(IDmtpReceivedPlugin.OnDmtpReceived), this, new DmtpMessageEventArgs(message));
 | 
			
		||||
        //            }
 | 
			
		||||
        //        }
 | 
			
		||||
 | 
			
		||||
        //        return false;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    else
 | 
			
		||||
        //    {
 | 
			
		||||
        //        return base.HandleReceivedData(byteBlock, requestInfo);
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override 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.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;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return base.HandleReceivedData(byteBlock, requestInfo);
 | 
			
		||||
            }
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor?.Close(false, e.Message);
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="request"></param>
 | 
			
		||||
        protected override void OnReceivedHttpRequest(HttpRequest request)
 | 
			
		||||
        protected override async Task OnReceivedHttpRequest(HttpRequest request)
 | 
			
		||||
        {
 | 
			
		||||
            if (request.IsMethod(DmtpUtility.Dmtp) && request.IsUpgrade() &&
 | 
			
		||||
                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());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            base.OnReceivedHttpRequest(request);
 | 
			
		||||
            await base.OnReceivedHttpRequest(request);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SetRpcActor(DmtpActor actor)
 | 
			
		||||
 
 | 
			
		||||
@@ -38,23 +38,24 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.Protocol = DmtpUtility.DmtpProtocol;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.Id"/>
 | 
			
		||||
        public string Id => this.DmtpActor.Id;
 | 
			
		||||
 | 
			
		||||
        #region 字段
 | 
			
		||||
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private SealedDmtpActor m_smtpActor;
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
 | 
			
		||||
        #endregion 字段
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 发送<see cref="IDmtpActor"/>关闭消息。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -153,7 +154,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
                }
 | 
			
		||||
                if (!this.Online)
 | 
			
		||||
                {
 | 
			
		||||
                    await base.ConnectAsync(timeout);
 | 
			
		||||
                    await base.ConnectAsync(timeout, token);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await this.m_smtpActor.HandshakeAsync(this.Config.GetValue(DmtpConfigExtension.VerifyTokenProperty),
 | 
			
		||||
@@ -235,20 +236,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            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/>
 | 
			
		||||
        protected override void LoadConfig(TouchSocketConfig config)
 | 
			
		||||
        {
 | 
			
		||||
@@ -274,14 +261,31 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnDmtpActorClose(DmtpActor actor, string msg)
 | 
			
		||||
        {
 | 
			
		||||
            base.Close(msg);
 | 
			
		||||
@@ -330,11 +334,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.OnRouting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void DmtpActorSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
        {
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 内部委托绑定
 | 
			
		||||
 | 
			
		||||
        #region 事件触发
 | 
			
		||||
 
 | 
			
		||||
@@ -68,14 +68,14 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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)
 | 
			
		||||
            {
 | 
			
		||||
                Id = e.Id,
 | 
			
		||||
                OnFindDmtpActor = this.m_allowRoute ? (this.m_findDmtpActor ?? this.OnServiceFindDmtpActor) : null
 | 
			
		||||
            });
 | 
			
		||||
            base.OnConnecting(socketClient, e);
 | 
			
		||||
            await base.OnConnecting(socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IDmtpActor OnServiceFindDmtpActor(string id)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,12 +40,12 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            this.Protocol = DmtpUtility.DmtpProtocol;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public IDmtpActor DmtpActor { get => this.m_smtpActor; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IDmtpActor.IsHandshaked"/>
 | 
			
		||||
        public bool IsHandshaked => this.DmtpActor != null && this.DmtpActor.IsHandshaked;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证超时时间,默认为3000ms
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -201,26 +201,23 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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.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;
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnConnected(ConnectedEventArgs e)
 | 
			
		||||
        protected override async Task OnConnected(ConnectedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_smtpActor.Id = this.Id;
 | 
			
		||||
            base.OnConnected(e);
 | 
			
		||||
            await base.OnConnected(e);
 | 
			
		||||
 | 
			
		||||
            Task.Run(async () =>
 | 
			
		||||
            _ = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(this.VerifyTimeout);
 | 
			
		||||
                if (!this.IsHandshaked)
 | 
			
		||||
@@ -232,15 +229,10 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.DmtpActor.Close(false, e.Message);
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(waitSetId.NewId);
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisDmtpActorOutputSend(DmtpActor actor, ArraySegment<byte>[] transferBytes)
 | 
			
		||||
@@ -248,6 +240,11 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            base.Send(transferBytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThisOnResetId(DmtpActor rpcActor, WaitSetId waitSetId)
 | 
			
		||||
        {
 | 
			
		||||
            this.DirectResetId(waitSetId.NewId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 发送
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -75,20 +75,20 @@ namespace ThingsGateway.Foundation.Dmtp.Rpc
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var message = DmtpMessage.CreateFrom(byteBlock);
 | 
			
		||||
            var message = DmtpMessage.CreateFrom(e.ByteBlock);
 | 
			
		||||
            if (!client.InputReceivedData(message))
 | 
			
		||||
            {
 | 
			
		||||
                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));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 字段
 | 
			
		||||
#pragma warning disable CS0414
 | 
			
		||||
        private bool m_allowRoute;
 | 
			
		||||
#pragma warning restore CS0414
 | 
			
		||||
 | 
			
		||||
        private ClientWebSocket m_client;
 | 
			
		||||
        private Func<string, IDmtpActor> m_findDmtpActor;
 | 
			
		||||
        private ValueCounter m_receiveCounter;
 | 
			
		||||
@@ -236,18 +234,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            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>
 | 
			
		||||
@@ -297,7 +283,6 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
 | 
			
		||||
            if (this.Container.IsRegistered(typeof(IDmtpRouteService)))
 | 
			
		||||
            {
 | 
			
		||||
                this.m_allowRoute = true;
 | 
			
		||||
                this.m_findDmtpActor = this.Container.Resolve<IDmtpRouteService>().FindDmtpActor;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -421,10 +406,7 @@ namespace ThingsGateway.Foundation.Dmtp
 | 
			
		||||
            var message = (DmtpMessage)requestInfo;
 | 
			
		||||
            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 事件触发
 | 
			
		||||
 | 
			
		||||
        #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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1507,7 +1507,7 @@ namespace ThingsGateway.Foundation.Dmtp.FileTransfer
 | 
			
		||||
                    waitFileSection.Message = ex.Message;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                waitFileSection.Value.Dispose();
 | 
			
		||||
                waitFileSection.Value.SafeDispose();
 | 
			
		||||
                waitFileSection.Value = default;
 | 
			
		||||
                using (var byteBlock = new ByteBlock())
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -213,14 +213,11 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        protected override Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (requestInfo is HttpResponse response)
 | 
			
		||||
            if (e.RequestInfo is HttpResponse response)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.m_getContent)
 | 
			
		||||
                {
 | 
			
		||||
@@ -229,18 +226,18 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
                this.m_waitData.Set(response);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
            return base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override void OnConnecting(ConnectingEventArgs e)
 | 
			
		||||
        protected override async Task OnConnecting(ConnectingEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.Protocol = Protocol.Http;
 | 
			
		||||
            this.SetDataHandlingAdapter(new HttpClientDataHandlingAdapter());
 | 
			
		||||
            base.OnConnecting(e);
 | 
			
		||||
            await base.OnConnecting(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,8 @@ using System.Threading.Tasks;
 | 
			
		||||
using ThingsGateway.Foundation.Core;
 | 
			
		||||
using ThingsGateway.Foundation.Sockets;
 | 
			
		||||
 | 
			
		||||
using HttpClient = System.Net.Http.HttpClient;
 | 
			
		||||
using HttpMethod = System.Net.Http.HttpMethod;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Http
 | 
			
		||||
{
 | 
			
		||||
@@ -100,16 +102,6 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
            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)
 | 
			
		||||
        {
 | 
			
		||||
            this.Config = config;
 | 
			
		||||
 
 | 
			
		||||
@@ -39,34 +39,35 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void OnConnecting(ConnectingEventArgs e)
 | 
			
		||||
        protected override async Task OnConnecting(ConnectingEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.SetDataHandlingAdapter(new HttpServerDataHandlingAdapter());
 | 
			
		||||
            base.OnConnecting(e);
 | 
			
		||||
            await base.OnConnecting(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当收到到Http请求时。覆盖父类方法将不会触发插件。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected virtual void OnReceivedHttpRequest(HttpRequest request)
 | 
			
		||||
        protected virtual Task OnReceivedHttpRequest(HttpRequest request)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.PluginsManager.GetPluginCount(nameof(IHttpPlugin.OnHttpRequest)) > 0)
 | 
			
		||||
            {
 | 
			
		||||
                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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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>
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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>
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,8 +31,7 @@ namespace ThingsGateway.Foundation.Http
 | 
			
		||||
    public interface IHttpPlugin<in TClient> : IPlugin where TClient : IHttpSocketClient
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在收到Http请求时。注意:此插件的执行在<see cref="IHttpGetPlugin"/>,<see cref="IHttpPostPlugin"/>,
 | 
			
		||||
        /// <see cref="IHttpDeletePlugin"/>,<see cref="IHttpPutPlugin"/>之前。
 | 
			
		||||
        /// 在收到Http请求时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="client"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -75,7 +75,17 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token);
 | 
			
		||||
            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 发送
 | 
			
		||||
        public void Send(WSDataFrame dataFrame, bool endOfMessage = true)
 | 
			
		||||
        {
 | 
			
		||||
@@ -145,7 +155,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_client.RemoveValue(WebSocketClientExtensions.WebSocketProperty);
 | 
			
		||||
            this.m_client.RemoveValue(WebSocketClientExtension.WebSocketProperty);
 | 
			
		||||
            this.m_resetEventForComplateRead.SafeDispose();
 | 
			
		||||
            this.m_resetEventForRead.SafeDispose();
 | 
			
		||||
            this.m_dataFrame = null;
 | 
			
		||||
@@ -154,8 +164,8 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
 | 
			
		||||
        private void ComplateRead()
 | 
			
		||||
        {
 | 
			
		||||
            this.m_resetEventForComplateRead.Set();
 | 
			
		||||
            this.m_dataFrame = default;
 | 
			
		||||
            this.m_resetEventForComplateRead.Set();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -41,5 +41,10 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        /// WebSocket数据帧
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public WSDataFrame DataFrame { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 连接已关闭
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsClosed => this.DataFrame == null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,10 +39,14 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="dataFrame"></param>
 | 
			
		||||
        protected override void OnHandleWSDataFrame(WSDataFrame dataFrame)
 | 
			
		||||
        protected override async Task OnReceivedWSDataFrame(WSDataFrame dataFrame)
 | 
			
		||||
        {
 | 
			
		||||
            this.Received?.Invoke(this, dataFrame);
 | 
			
		||||
            base.OnHandleWSDataFrame(dataFrame);
 | 
			
		||||
            if (this.Received != null)
 | 
			
		||||
            {
 | 
			
		||||
                await this.Received.Invoke(this, dataFrame);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await base.OnReceivedWSDataFrame(dataFrame);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -211,20 +215,44 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
 | 
			
		||||
        #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/>
 | 
			
		||||
        protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.GetHandshaked())
 | 
			
		||||
            {
 | 
			
		||||
                var dataFrame = (WSDataFrame)requestInfo;
 | 
			
		||||
                this.OnHandleWSDataFrame(dataFrame);
 | 
			
		||||
                var dataFrame = (WSDataFrame)e.RequestInfo;
 | 
			
		||||
                await this.OnReceivedWSDataFrame(dataFrame);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (requestInfo is HttpResponse response)
 | 
			
		||||
                if (e.RequestInfo is HttpResponse response)
 | 
			
		||||
                {
 | 
			
		||||
                    response.Flag = false;
 | 
			
		||||
                    base.HandleReceivedData(byteBlock, requestInfo);
 | 
			
		||||
                    await base.ReceivedData(e);
 | 
			
		||||
                    SpinWait.SpinUntil(() =>
 | 
			
		||||
                    {
 | 
			
		||||
                        return (bool)response.Flag;
 | 
			
		||||
@@ -232,32 +260,32 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
            await base.ReceivedData(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.SetValue(WebSocketFeature.HandshakedProperty, false);
 | 
			
		||||
            if (this.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket))
 | 
			
		||||
            if (this.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
 | 
			
		||||
            {
 | 
			
		||||
                _ = internalWebSocket.TryInputReceiveAsync(null);
 | 
			
		||||
            }
 | 
			
		||||
            base.OnDisconnected(e);
 | 
			
		||||
            await base.OnDisconnected(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当收到WS数据时。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <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;
 | 
			
		||||
                }
 | 
			
		||||
@@ -265,7 +293,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
 | 
			
		||||
            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));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// WebSocket适配器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class WebSocketDataHandlingAdapter : SingleStreamDataHandlingAdapter
 | 
			
		||||
    public sealed class WebSocketDataHandlingAdapter : SingleStreamDataHandlingAdapter
 | 
			
		||||
    {
 | 
			
		||||
        private WSDataFrame m_dataFrameTemp;
 | 
			
		||||
 | 
			
		||||
@@ -42,16 +42,6 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private ByteBlock m_tempByteBlock;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanSendRequestInfo => false;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanSplicingSend => false;
 | 
			
		||||
 | 
			
		||||
        /// <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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -30,5 +30,5 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="dataFrame"></param>
 | 
			
		||||
    public delegate void WSDataFrameEventHandler<TClient>(TClient client, WSDataFrame dataFrame);
 | 
			
		||||
    public delegate Task WSDataFrameEventHandler<TClient>(TClient client, WSDataFrame dataFrame);
 | 
			
		||||
}
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// WSClientExtensions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class WebSocketClientExtensions
 | 
			
		||||
    public static class WebSocketClientExtension
 | 
			
		||||
    {
 | 
			
		||||
        #region DependencyProperty
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// WebSocketConfigExtensions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class WebSocketConfigExtensions
 | 
			
		||||
    public static class WebSocketConfigExtension
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构建WebSocketClient类客户端,并连接
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// WSDataFrame辅助扩展类
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class WebSocketDataFrameExtensions
 | 
			
		||||
    public static class WebSocketDataFrameExtension
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 追加二进制流
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// WebSocketServerExtensions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class WebSocketServerExtensions
 | 
			
		||||
    public static class WebSocketServerExtension
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 转化Protocol协议标识为<see cref="Protocol.WebSocket"/>
 | 
			
		||||
@@ -49,7 +49,8 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                    {
 | 
			
		||||
                        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)
 | 
			
		||||
                    {
 | 
			
		||||
                        return false;
 | 
			
		||||
@@ -63,9 +64,10 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                        using (var byteBlock = new 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;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -74,7 +76,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                        using (var byteBlock = new ByteBlock())
 | 
			
		||||
                        {
 | 
			
		||||
                            args.Context.Response.Build(byteBlock);
 | 
			
		||||
                            await client.DefaultSendAsync(byteBlock);
 | 
			
		||||
                            await client.DefaultSendAsync(byteBlock).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        client.Close("主动拒绝WebSocket连接");
 | 
			
		||||
@@ -68,7 +68,14 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        /// <param name="token"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        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>
 | 
			
		||||
        /// 采用WebSocket协议,发送WS数据。发送结束后,请及时释放<see cref="WSDataFrame"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证连接
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<IHttpSocketClient, HttpContext, bool> VerifyConnection { get; set; }
 | 
			
		||||
        public Func<IHttpSocketClient, HttpContext, Task<bool>> VerifyConnection { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用于WebSocket连接的路径,默认为“/ws”
 | 
			
		||||
@@ -98,7 +98,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        {
 | 
			
		||||
            if (client.Protocol == Protocol.Http)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.VerifyConnection.Invoke(client, e.Context))
 | 
			
		||||
                if (await this.VerifyConnection.Invoke(client, e.Context))
 | 
			
		||||
                {
 | 
			
		||||
                    e.Handled = true;
 | 
			
		||||
                    _ = client.SwitchProtocolToWebSocket(e.Context);
 | 
			
		||||
@@ -117,7 +117,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        public async Task OnTcpDisconnected(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            client.SetValue(HandshakedProperty, false);
 | 
			
		||||
            if (client.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket))
 | 
			
		||||
            if (client.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
 | 
			
		||||
            {
 | 
			
		||||
                _ = internalWebSocket.TryInputReceiveAsync(null);
 | 
			
		||||
            }
 | 
			
		||||
@@ -145,6 +145,21 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
        /// <param name="func"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        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;
 | 
			
		||||
            return this;
 | 
			
		||||
@@ -186,7 +201,7 @@ namespace ThingsGateway.Foundation.Http.WebSockets
 | 
			
		||||
                ((HttpSocketClient)client).PongWS();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (client.TryGetValue(WebSocketClientExtensions.WebSocketProperty, out var internalWebSocket))
 | 
			
		||||
            if (client.TryGetValue(WebSocketClientExtension.WebSocketProperty, out var internalWebSocket))
 | 
			
		||||
            {
 | 
			
		||||
                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));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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 (this.WSUrl == "/" || context.Request.UrlEquals(this.WSUrl))
 | 
			
		||||
 
 | 
			
		||||
@@ -41,12 +41,6 @@ namespace ThingsGateway.Foundation.Rpc
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        ExtensionAsync = 2,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 包含扩展(源代码生成无效)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [Obsolete("该值已被弃用,请使用颗粒度更小的配置", true)]
 | 
			
		||||
        IncludeExtension = 4,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 生成实例类同步代码(源代码生成无效)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ namespace ThingsGateway.Foundation.Serial;
 | 
			
		||||
/// <typeparam name="TClient"></typeparam>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void SerialConnectingEventHandler<TClient>(TClient client, SerialConnectingEventArgs e);
 | 
			
		||||
public delegate Task SerialConnectingEventHandler<TClient>(TClient client, SerialConnectingEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 客户端连接事件。
 | 
			
		||||
 
 | 
			
		||||
@@ -15,21 +15,7 @@ namespace ThingsGateway.Foundation.Serial;
 | 
			
		||||
/// <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; }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -53,9 +53,9 @@ public interface ISerialSessionBase : IClient, ISender, IDefaultSender, IPluginO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收模式
 | 
			
		||||
    /// 判断是否在线
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public ReceiveType ReceiveType { get; }
 | 
			
		||||
    bool Online { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 串口描述
 | 
			
		||||
 
 | 
			
		||||
@@ -21,21 +21,23 @@ public abstract class BaseSerial : DependencyObject, ISerial
 | 
			
		||||
    /// 同步根。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    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/>
 | 
			
		||||
    public virtual int SendBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => m_sendBufferSize;
 | 
			
		||||
        set => m_sendBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
        get => this.m_sendBufferSize;
 | 
			
		||||
        set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public virtual int ReceiveBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => m_receiveBufferSize;
 | 
			
		||||
        set => m_receiveBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
        get => this.m_receiveBufferSize;
 | 
			
		||||
        set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public ILog Logger { get; set; }
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -14,6 +14,7 @@ using System.IO.Ports;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Serial;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc cref="SerialSessionBase"/>
 | 
			
		||||
public class SerialSession : SerialSessionBase
 | 
			
		||||
{
 | 
			
		||||
@@ -22,15 +23,18 @@ public class SerialSession : SerialSessionBase
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public ReceivedEventHandler<SerialSession> Received { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="byteBlock"></param>
 | 
			
		||||
    /// <param name="requestInfo"></param>
 | 
			
		||||
    protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    protected override async Task ReceivedData(ReceivedDataEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        this.Received?.Invoke(this, byteBlock, requestInfo);
 | 
			
		||||
        return false;
 | 
			
		||||
        if (this.Received != null)
 | 
			
		||||
        {
 | 
			
		||||
            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()
 | 
			
		||||
    {
 | 
			
		||||
        this.Protocol = SerialPort;
 | 
			
		||||
        this.m_receiveCounter = new ValueCounter
 | 
			
		||||
        {
 | 
			
		||||
            Period = TimeSpan.FromSeconds(1),
 | 
			
		||||
            OnPeriod = this.OnReceivePeriod
 | 
			
		||||
        };
 | 
			
		||||
        this.m_sendCounter = new ValueCounter
 | 
			
		||||
        {
 | 
			
		||||
            Period = TimeSpan.FromSeconds(1),
 | 
			
		||||
            OnPeriod = this.OnSendPeriod
 | 
			
		||||
        };
 | 
			
		||||
        this.m_serialCore = new InternalSerialCore();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #region 变量
 | 
			
		||||
 | 
			
		||||
    private DelaySender m_delaySender;
 | 
			
		||||
    private long m_bufferRate = 1;
 | 
			
		||||
    private bool m_online => MainSerialPort?.IsOpen == true;
 | 
			
		||||
    private ValueCounter m_receiveCounter;
 | 
			
		||||
    private ValueCounter m_sendCounter;
 | 
			
		||||
 | 
			
		||||
    private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
 | 
			
		||||
    private readonly InternalSerialCore m_serialCore;
 | 
			
		||||
    #endregion 变量
 | 
			
		||||
 | 
			
		||||
    #region 事件
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public ConnectedEventHandler<ISerialSession> Connected { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public SerialConnectingEventHandler<ISerialSession> Connecting { get; set; }
 | 
			
		||||
 | 
			
		||||
@@ -82,26 +75,28 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public DisconnectEventHandler<ISerialSessionBase> Disconnecting { get; set; }
 | 
			
		||||
 | 
			
		||||
    private void PrivateOnConnected(object o)
 | 
			
		||||
    private Task PrivateOnConnected(object o)
 | 
			
		||||
    {
 | 
			
		||||
        var e = (ConnectedEventArgs)o;
 | 
			
		||||
        this.OnConnected(e);
 | 
			
		||||
        if (e.Handled)
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.PluginsManager.Raise(nameof(ITcpConnectedPlugin.OnTcpConnected), this, e);
 | 
			
		||||
        return this.OnConnected((ConnectedEventArgs)o);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 已经建立Tcp连接
 | 
			
		||||
    /// 已经建立连接
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    protected virtual void OnConnected(ConnectedEventArgs e)
 | 
			
		||||
    protected virtual async Task OnConnected(ConnectedEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
@@ -109,30 +104,33 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void PrivateOnConnecting(SerialConnectingEventArgs e)
 | 
			
		||||
    private Task PrivateOnConnecting(SerialConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        if (this.CanSetDataHandlingAdapter)
 | 
			
		||||
        {
 | 
			
		||||
            this.SetDataHandlingAdapter(this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty).Invoke());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.OnConnecting(e);
 | 
			
		||||
        if (e.Handled)
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.PluginsManager.Raise(nameof(ITcpConnectingPlugin.OnTcpConnecting), this, e);
 | 
			
		||||
        return this.OnConnecting(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 准备连接的时候,此时已初始化Socket,但是并未建立Tcp连接
 | 
			
		||||
    /// 准备连接的时候,此时并未建立连接
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    protected virtual void OnConnecting(SerialConnectingEventArgs e)
 | 
			
		||||
    protected virtual async Task OnConnecting(SerialConnectingEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
@@ -140,25 +138,30 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void PrivateOnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
    private Task PrivateOnDisconnected(object obj)
 | 
			
		||||
    {
 | 
			
		||||
        this.OnDisconnected(e);
 | 
			
		||||
        if (e.Handled)
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.PluginsManager.Raise(nameof(ITcpDisconnectedPlugin.OnTcpDisconnected), this, e);
 | 
			
		||||
        this.m_receiver?.TryInputReceive(default, default);
 | 
			
		||||
        return this.OnDisconnected((DisconnectEventArgs)obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 断开连接。在客户端未设置连接状态时,不会触发
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    protected virtual void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
    protected virtual async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
@@ -166,28 +169,29 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void PrivateOnDisconnecting(DisconnectEventArgs e)
 | 
			
		||||
    private Task PrivateOnDisconnecting(object obj)
 | 
			
		||||
    {
 | 
			
		||||
        this.OnDisconnecting(e);
 | 
			
		||||
        if (e.Handled)
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.PluginsManager.Raise(nameof(ITcpDisconnectingPlugin.OnTcpDisconnecting), this, e);
 | 
			
		||||
        return this.OnDisconnecting((DisconnectEventArgs)obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 即将断开连接(仅主动断开时有效)。
 | 
			
		||||
    /// <para>
 | 
			
		||||
    /// 当主动调用Close断开时。
 | 
			
		||||
    /// </para>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    protected virtual void OnDisconnecting(DisconnectEventArgs e)
 | 
			
		||||
    protected virtual async Task OnDisconnecting(DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
@@ -200,16 +204,10 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    #region 属性
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public DateTime LastReceivedTime => this.m_receiveCounter.LastIncrement;
 | 
			
		||||
    public DateTime LastReceivedTime => this.GetTcpCore().ReceiveCounter.LastIncrement;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public DateTime LastSendTime => this.m_sendCounter.LastIncrement;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
 | 
			
		||||
    public DateTime LastSendTime => this.GetTcpCore().SendCounter.LastIncrement;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public IContainer Container { get; private set; }
 | 
			
		||||
@@ -223,10 +221,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public SingleStreamDataHandlingAdapter DataHandlingAdapter { get; private set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public SerialProperty SerialProperty { get; private set; }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public SerialPort MainSerialPort { get; private set; }
 | 
			
		||||
@@ -241,9 +236,6 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    public IPluginsManager PluginsManager { get; private set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public ReceiveType ReceiveType { get; private set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public Protocol Protocol { get; set; }
 | 
			
		||||
@@ -261,32 +253,13 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_online)
 | 
			
		||||
            {
 | 
			
		||||
                this.PrivateOnDisconnecting(new DisconnectEventArgs(true, msg));
 | 
			
		||||
 | 
			
		||||
                Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, msg));
 | 
			
		||||
                this.MainSerialPort.TryClose();
 | 
			
		||||
 | 
			
		||||
                this.MainSerialPort.SafeDispose();
 | 
			
		||||
                this.m_delaySender.SafeDispose();
 | 
			
		||||
                this.DataHandlingAdapter.SafeDispose();
 | 
			
		||||
                this.PrivateOnDisconnected(new DisconnectEventArgs(true, msg));
 | 
			
		||||
                this.BreakOut(default, 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>
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -298,15 +271,8 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        {
 | 
			
		||||
            if (this.m_online)
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                this.MainSerialPort.TryClose();
 | 
			
		||||
                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)}主动断开"));
 | 
			
		||||
                Task.Factory.StartNew(this.PrivateOnDisconnecting, new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开"));
 | 
			
		||||
                this.BreakOut(default, true, $"{nameof(Dispose)}主动断开");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        base.Dispose(disposing);
 | 
			
		||||
@@ -315,6 +281,7 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    #endregion 断开操作
 | 
			
		||||
 | 
			
		||||
    #region Connect
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 打开串口
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -332,25 +299,32 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
            }
 | 
			
		||||
            if (this.Config == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("配置文件不能为空。");
 | 
			
		||||
                throw new ArgumentNullException(nameof(this.Config), "配置文件不能为空。");
 | 
			
		||||
            }
 | 
			
		||||
            var serialProperty = this.Config.GetValue(SerialConfigExtension.SerialProperty) ?? throw new ArgumentNullException("串口配置不能为空。");
 | 
			
		||||
 | 
			
		||||
            this.MainSerialPort.SafeDispose();
 | 
			
		||||
            var serialPort = CreateSerial(serialProperty);
 | 
			
		||||
            var args = new SerialConnectingEventArgs(this.MainSerialPort);
 | 
			
		||||
            this.PrivateOnConnecting(args);
 | 
			
		||||
            this.PrivateOnConnecting(new(serialPort))
 | 
			
		||||
                .ConfigureAwait(false)
 | 
			
		||||
                .GetAwaiter()
 | 
			
		||||
                .GetResult();
 | 
			
		||||
 | 
			
		||||
            serialPort.Open();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            this.SetSerialPort(serialPort);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            this.BeginReceive();
 | 
			
		||||
            this.PrivateOnConnected(new ConnectedEventArgs());
 | 
			
		||||
 | 
			
		||||
            Task.Factory.StartNew(this.PrivateOnConnected, new ConnectedEventArgs());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private void BeginReceive()
 | 
			
		||||
    {
 | 
			
		||||
        this.GetTcpCore().BeginIocpReceive();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public virtual ISerialSession Connect()
 | 
			
		||||
    {
 | 
			
		||||
@@ -366,43 +340,66 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
    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/>
 | 
			
		||||
    public override int ReceiveBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => base.ReceiveBufferSize;
 | 
			
		||||
        get => this.GetTcpCore().ReceiveBufferSize;
 | 
			
		||||
        set
 | 
			
		||||
        {
 | 
			
		||||
            base.ReceiveBufferSize = value;
 | 
			
		||||
            if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
 | 
			
		||||
            {
 | 
			
		||||
                this.MainSerialPort.ReadBufferSize = base.ReceiveBufferSize;
 | 
			
		||||
            }
 | 
			
		||||
            this.GetTcpCore().ReceiveBufferSize = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override int SendBufferSize
 | 
			
		||||
    {
 | 
			
		||||
        get => base.SendBufferSize;
 | 
			
		||||
        get => this.GetTcpCore().SendBufferSize;
 | 
			
		||||
        set
 | 
			
		||||
        {
 | 
			
		||||
            base.SendBufferSize = value;
 | 
			
		||||
            if (this.MainSerialPort != null && !MainSerialPort.IsOpen)
 | 
			
		||||
            {
 | 
			
		||||
                this.MainSerialPort.WriteBufferSize = base.SendBufferSize;
 | 
			
		||||
            }
 | 
			
		||||
            this.GetTcpCore().SendBufferSize = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -480,32 +477,24 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
 | 
			
		||||
    private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        if (this.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
 | 
			
		||||
        if (this.m_receiver != null)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
            if (this.m_receiver.TryInputReceive(byteBlock, requestInfo))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        this.ReceivedData(new ReceivedDataEventArgs(byteBlock, requestInfo)).GetFalseAwaitResult();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 处理已接收到的数据。
 | 
			
		||||
    /// 当收到适配器处理的数据时。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="byteBlock">以二进制流形式传递</param>
 | 
			
		||||
    /// <param name="requestInfo">以解析的数据对象传递</param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    /// <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>
 | 
			
		||||
@@ -515,12 +504,12 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    /// <param name="offset">偏移</param>
 | 
			
		||||
    /// <param name="length">长度</param>
 | 
			
		||||
    /// <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);
 | 
			
		||||
            this.PluginsManager.Raise(nameof(ITcpSendingPlugin.OnTcpSending), this, args);
 | 
			
		||||
            await this.PluginsManager.RaiseAsync(nameof(ITcpSendingPlugin.OnTcpSending), this, args).ConfigureAwait(false);
 | 
			
		||||
            return args.IsPermitOperation;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -534,16 +523,6 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    {
 | 
			
		||||
        this.SerialProperty = config.GetValue(SerialConfigExtension.SerialProperty);
 | 
			
		||||
        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>
 | 
			
		||||
@@ -567,33 +546,10 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        adapter.OnLoaded(this);
 | 
			
		||||
        adapter.ReceivedCallBack = this.PrivateHandleReceivedData;
 | 
			
		||||
        adapter.SendCallBack = this.DefaultSend;
 | 
			
		||||
        adapter.SendAsyncCallBack = this.DefaultSendAsync;
 | 
			
		||||
        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)
 | 
			
		||||
    {
 | 
			
		||||
        SerialPort serialPort = new(serialProperty.PortName, serialProperty.BaudRate, serialProperty.Parity, serialProperty.DataBits, serialProperty.StopBits)
 | 
			
		||||
@@ -604,88 +560,6 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        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 同步发送
 | 
			
		||||
@@ -757,12 +631,14 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
            {
 | 
			
		||||
                length += item.Count;
 | 
			
		||||
            }
 | 
			
		||||
            using var byteBlock = new ByteBlock(length);
 | 
			
		||||
            foreach (var item in transferBytes)
 | 
			
		||||
            using (var byteBlock = new ByteBlock(length))
 | 
			
		||||
            {
 | 
			
		||||
                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>
 | 
			
		||||
    /// <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>
 | 
			
		||||
    /// <param name="buffer"></param>
 | 
			
		||||
    /// <param name="offset"></param>
 | 
			
		||||
    /// <param name="length"></param>
 | 
			
		||||
    /// <exception cref="NotConnectedException"></exception>
 | 
			
		||||
    /// <exception cref="OverlengthException"></exception>
 | 
			
		||||
    /// <exception cref="Exception"></exception>
 | 
			
		||||
    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>
 | 
			
		||||
@@ -796,118 +674,78 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
    /// <exception cref="Exception"></exception>
 | 
			
		||||
    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>
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="transferBytes"><inheritdoc/></param>
 | 
			
		||||
    /// <exception cref="NotConnectedException"><inheritdoc/></exception>
 | 
			
		||||
    /// <exception cref="OverlengthException"><inheritdoc/></exception>
 | 
			
		||||
    /// <exception cref="Exception"><inheritdoc/></exception>
 | 
			
		||||
    /// <param name="transferBytes"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    /// <exception cref="ArgumentNullException"></exception>
 | 
			
		||||
    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 异步发送
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <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)
 | 
			
		||||
    {
 | 
			
		||||
        if (!this.m_online)
 | 
			
		||||
        if (this.SendingData(buffer, offset, length).GetFalseAwaitResult())
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotConnectedException(TouchSocketResource.NotConnected.GetDescription());
 | 
			
		||||
        }
 | 
			
		||||
        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);
 | 
			
		||||
            this.GetTcpCore().Send(buffer, offset, length);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <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 Task DefaultSendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
    public async 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 发送
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private void ProcessReceived(SerialReceivedEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
    #region 自定义
 | 
			
		||||
 | 
			
		||||
                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)
 | 
			
		||||
    {
 | 
			
		||||
@@ -917,15 +755,63 @@ public class SerialSessionBase : BaseSerial, ISerialSession
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        if (delaySenderOption != null)
 | 
			
		||||
        {
 | 
			
		||||
            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
 | 
			
		||||
}
 | 
			
		||||
@@ -34,21 +34,24 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// 同步根。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        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/>
 | 
			
		||||
        public virtual int SendBufferSize
 | 
			
		||||
        {
 | 
			
		||||
            get => m_sendBufferSize;
 | 
			
		||||
            set => m_sendBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
            get => this.m_sendBufferSize;
 | 
			
		||||
            set => this.m_sendBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public virtual int ReceiveBufferSize
 | 
			
		||||
        {
 | 
			
		||||
            get => m_receiveBufferSize;
 | 
			
		||||
            set => m_receiveBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
            get => this.m_receiveBufferSize;
 | 
			
		||||
            set => this.m_receiveBufferSize = value < 1024 ? 1024 : value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public ILog Logger { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,11 +32,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int SendTimeout { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 接收类型
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReceiveType ReceiveType { get; set; } = ReceiveType.Iocp;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否使用地址复用
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -44,23 +44,22 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// 在NAT服务器收到数据时。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected override sealed void OnReceived(NATSocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override sealed async Task OnReceived(NATSocketClient socketClient, ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            var data = this.OnNATReceived(socketClient, byteBlock, requestInfo);
 | 
			
		||||
            await EasyTask.CompletedTask;
 | 
			
		||||
            var data = this.OnNATReceived(socketClient, e);
 | 
			
		||||
            if (data != null)
 | 
			
		||||
            {
 | 
			
		||||
                socketClient.SendToTargetClient(data, 0, data.Length);
 | 
			
		||||
@@ -82,12 +81,11 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="tcpClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <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();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,7 +31,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    public class NATSocketClient : SocketClient
 | 
			
		||||
    {
 | 
			
		||||
        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>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -100,18 +100,19 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override void OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        protected override async Task OnDisconnected(DisconnectEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var client in this.m_targetClients)
 | 
			
		||||
            {
 | 
			
		||||
                client.TryShutdown();
 | 
			
		||||
                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)
 | 
			
		||||
            {
 | 
			
		||||
                if (typeof(ReconnectionPlugin<>) == item.GetType().GetGenericTypeDefinition())
 | 
			
		||||
@@ -125,8 +126,9 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            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)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
@@ -134,7 +136,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var data = this.m_internalTargetClientRev?.Invoke(this, client, byteBlock, requestInfo);
 | 
			
		||||
                var data = this.m_internalTargetClientRev?.Invoke(this, client, e);
 | 
			
		||||
                if (data != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.CanSend)
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -27,11 +27,10 @@ using System.Net.Sockets;
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// TCP泛型服务器,由使用者自己指定<see cref="SocketClient"/>类型。
 | 
			
		||||
    /// Tcp泛型服务器,由使用者自己指定<see cref="SocketClient"/>类型。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class TcpService<TClient> : TcpServiceBase, ITcpService<TClient> where TClient : SocketClient, new()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构造函数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -102,25 +101,17 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 即将断开连接(仅主动断开时有效)。
 | 
			
		||||
        /// <para>
 | 
			
		||||
        /// 当主动调用Close断开时,可通过<see cref="MsgPermitEventArgs.IsPermitOperation"/>终止断开行为。
 | 
			
		||||
        /// </para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public DisconnectEventHandler<TClient> Disconnecting { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当客户端Id被修改时触发。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IdChangedEventHandler<TClient> IdChanged { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
@@ -128,9 +119,9 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
@@ -138,9 +129,9 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
@@ -148,20 +139,19 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected override sealed void OnClientReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected override sealed Task OnClientReceivedData(ISocketClient socketClient, ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.OnReceived((TClient)socketClient, byteBlock, requestInfo);
 | 
			
		||||
            return this.OnReceived((TClient)socketClient, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -169,9 +159,13 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
@@ -179,9 +173,13 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
@@ -189,32 +187,37 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
        /// 即将断开连接(仅主动断开时有效)。
 | 
			
		||||
        /// <para>
 | 
			
		||||
        /// 当主动调用Close断开时,可通过<see cref="MsgPermitEventArgs.IsPermitOperation"/>终止断开行为。
 | 
			
		||||
        /// </para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></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>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected virtual void OnReceived(TClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected virtual Task OnReceived(TClient socketClient, ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 事件
 | 
			
		||||
@@ -224,7 +227,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            return Interlocked.Increment(ref this.m_nextId).ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取下一个新Id
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -363,7 +365,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public override IService Setup(TouchSocketConfig config)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            if (config == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(config));
 | 
			
		||||
@@ -434,7 +435,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
                            ReuseAddress = this.Config.GetValue(TouchSocketConfigExtension.ReuseAddressProperty),
 | 
			
		||||
                            NoDelay = this.Config.GetValue(TouchSocketConfigExtension.NoDelayProperty),
 | 
			
		||||
                            Adapter = this.Config.GetValue(TouchSocketConfigExtension.TcpDataHandlingAdapterProperty),
 | 
			
		||||
                            ReceiveType = this.Config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty)
 | 
			
		||||
                        };
 | 
			
		||||
                        option.Backlog = this.Config.GetValue(TouchSocketConfigExtension.BacklogProperty) ?? option.Backlog;
 | 
			
		||||
                        option.SendTimeout = this.Config.GetValue(TouchSocketConfigExtension.SendTimeoutProperty);
 | 
			
		||||
@@ -540,11 +540,11 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
                this.Clear();
 | 
			
		||||
 | 
			
		||||
                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.PluginsManager?.SafeDispose();
 | 
			
		||||
                this.PluginsManager.SafeDispose();
 | 
			
		||||
            }
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
@@ -691,7 +691,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            return new NormalDataHandlingAdapter();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnClientSocketInit(object obj)
 | 
			
		||||
        private async Task OnClientSocketInit(object obj)
 | 
			
		||||
        {
 | 
			
		||||
            var tuple = (Tuple<Socket, TcpNetworkMonitor>)obj;
 | 
			
		||||
            var socket = tuple.Item1;
 | 
			
		||||
@@ -717,30 +717,35 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
                {
 | 
			
		||||
                    client.SetDataHandlingAdapter(this.GetAdapter(monitor));
 | 
			
		||||
                }
 | 
			
		||||
                client.InternalInitialized();
 | 
			
		||||
 | 
			
		||||
                await client.InternalInitialized();
 | 
			
		||||
 | 
			
		||||
                var args = new ConnectingEventArgs(socket)
 | 
			
		||||
                {
 | 
			
		||||
                    Id = this.GetNextNewId()
 | 
			
		||||
                };
 | 
			
		||||
                client.InternalConnecting(args);//Connecting
 | 
			
		||||
                await client.InternalConnecting(args);//Connecting
 | 
			
		||||
                if (args.IsPermitOperation)
 | 
			
		||||
                {
 | 
			
		||||
                    client.InternalSetId(args.Id);
 | 
			
		||||
                    if (!client.MainSocket.Connected)
 | 
			
		||||
                    if (!socket.Connected)
 | 
			
		||||
                    {
 | 
			
		||||
                        client.MainSocket.SafeDispose();
 | 
			
		||||
                        socket.SafeDispose();
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (this.m_socketClients.TryAdd(client))
 | 
			
		||||
                    {
 | 
			
		||||
                        client.InternalConnected(new ConnectedEventArgs());
 | 
			
		||||
 | 
			
		||||
                        _ = client.InternalConnected(new ConnectedEventArgs());
 | 
			
		||||
                        if (!socket.Connected)
 | 
			
		||||
                        {
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (monitor.Option.UseSsl)
 | 
			
		||||
                        {
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                client.BeginReceiveSsl(monitor.Option.ServiceSslOption);
 | 
			
		||||
                                await client.AuthenticateAsync(monitor.Option.ServiceSslOption);
 | 
			
		||||
                                _ = client.BeginReceiveSsl();
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex)
 | 
			
		||||
                            {
 | 
			
		||||
@@ -772,7 +777,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// TCP服务器
 | 
			
		||||
    /// Tcp服务器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class TcpService : TcpService<SocketClient>
 | 
			
		||||
    {
 | 
			
		||||
@@ -781,16 +786,14 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReceivedEventHandler<SocketClient> Received { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected override void OnReceived(SocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        protected override Task OnReceived(SocketClient socketClient, ReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.Received?.Invoke(socketClient, byteBlock, requestInfo);
 | 
			
		||||
            base.OnReceived(socketClient, byteBlock, requestInfo);
 | 
			
		||||
            if (this.Received != null)
 | 
			
		||||
            {
 | 
			
		||||
                return this.Received.Invoke(socketClient, e);
 | 
			
		||||
            }
 | 
			
		||||
            return EasyTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
@@ -122,29 +123,64 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        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>
 | 
			
		||||
@@ -152,39 +188,35 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected abstract void OnClientConnected(ISocketClient socketClient, ConnectedEventArgs e);
 | 
			
		||||
        protected abstract Task OnClientConnected(ISocketClient socketClient, ConnectedEventArgs e);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 客户端请求连接
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected abstract void OnClientConnecting(ISocketClient socketClient, ConnectingEventArgs e);
 | 
			
		||||
        protected abstract Task OnClientConnecting(ISocketClient socketClient, ConnectingEventArgs e);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 客户端断开连接
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected abstract void OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e);
 | 
			
		||||
        protected abstract Task OnClientDisconnected(ISocketClient socketClient, DisconnectEventArgs e);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 即将断开连接(仅主动断开时有效)。
 | 
			
		||||
        /// <para>
 | 
			
		||||
        /// 当主动调用Close断开时,可通过<see cref="MsgPermitEventArgs.IsPermitOperation"/>终止断开行为。
 | 
			
		||||
        /// </para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected abstract void OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e);
 | 
			
		||||
        protected abstract Task OnClientDisconnecting(ISocketClient socketClient, DisconnectEventArgs e);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 收到数据时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="socketClient"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected abstract void OnClientReceivedData(ISocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo);
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        protected abstract Task OnClientReceivedData(ISocketClient socketClient, ReceivedDataEventArgs e);
 | 
			
		||||
 | 
			
		||||
        #region Id发送
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,17 +36,20 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当收到数据时
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public UdpReceivedEventHandler Received { get; set; }
 | 
			
		||||
        public UdpReceivedEventHandler<UdpSession> Received { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="remoteEndPoint"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        protected override void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        protected override async Task ReceivedData(UdpReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理未经过适配器的数据。返回值表示是否继续向下传递。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理经过适配器后的数据。返回值表示是否继续向下传递。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -342,7 +335,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
                this.PluginsManager.Raise(nameof(IServerStartedPlugin.OnServerStarted), this, new ServiceStateEventArgs(this.ServerState, ex) { Message = ex.Message });
 | 
			
		||||
                throw;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -391,11 +383,9 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理已接收到的数据。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="remoteEndPoint"></param>
 | 
			
		||||
        /// <param name="byteBlock">以二进制流形式传递</param>
 | 
			
		||||
        /// <param name="requestInfo">以解析的数据对象传递</param>
 | 
			
		||||
        protected virtual void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        protected virtual Task ReceivedData(UdpReceivedDataEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            return this.PluginsManager.RaiseAsync(nameof(IUdpReceivedPlugin.OnUdpReceived), this, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -492,7 +482,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
            #endregion Windows下UDP连接被重置错误10054
 | 
			
		||||
 | 
			
		||||
            this.PreviewBind(socket);
 | 
			
		||||
 | 
			
		||||
@@ -500,55 +490,48 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
 | 
			
		||||
            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:
 | 
			
		||||
                    {
 | 
			
		||||
#if NET45_OR_GREATER||NET6_0_OR_GREATER
 | 
			
		||||
                        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
 | 
			
		||||
                        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模式");
 | 
			
		||||
                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
 | 
			
		||||
            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()
 | 
			
		||||
@@ -577,10 +560,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.LastReceivedTime = DateTime.Now;
 | 
			
		||||
                if (this.OnHandleRawBuffer?.Invoke(byteBlock) == false)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                if (this.DisposedValue)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -609,21 +588,14 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
 | 
			
		||||
        private void PrivateHandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
 | 
			
		||||
            if (this.m_receiver != null)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.PluginsManager.Enable)
 | 
			
		||||
            {
 | 
			
		||||
                var args = new UdpReceivedDataEventArgs(remoteEndPoint, byteBlock, requestInfo);
 | 
			
		||||
                this.PluginsManager.Raise(nameof(IUdpReceivedPlugin.OnUdpReceived), this, args);
 | 
			
		||||
                if (args.Handled)
 | 
			
		||||
                if (this.m_receiver.TryInputReceive(byteBlock, requestInfo))
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this.HandleReceivedData(remoteEndPoint, byteBlock, requestInfo);
 | 
			
		||||
            this.ReceivedData(new UdpReceivedDataEventArgs(remoteEndPoint, byteBlock, requestInfo)).GetFalseAwaitResult();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 向默认远程同步发送
 | 
			
		||||
@@ -663,7 +635,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            {
 | 
			
		||||
                throw new NotSupportedException($"当前适配器不支持对象发送。");
 | 
			
		||||
            }
 | 
			
		||||
            this.DataHandlingAdapter.SendInput(requestInfo);
 | 
			
		||||
            //this.DataHandlingAdapter.SendInput(requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 向默认远程同步发送
 | 
			
		||||
@@ -682,9 +654,9 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        public virtual Task SendAsync(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return Task.Run(() =>
 | 
			
		||||
              {
 | 
			
		||||
                  this.Send(buffer, offset, length);
 | 
			
		||||
              });
 | 
			
		||||
            {
 | 
			
		||||
                this.Send(buffer, offset, length);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -737,9 +709,9 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        public virtual Task SendAsync(EndPoint remoteEP, byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            return Task.Run(() =>
 | 
			
		||||
             {
 | 
			
		||||
                 this.Send(remoteEP, buffer, offset, length);
 | 
			
		||||
             });
 | 
			
		||||
            {
 | 
			
		||||
                this.Send(remoteEP, buffer, offset, length);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 向设置的远程异步发送
 | 
			
		||||
@@ -906,5 +878,23 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,67 +22,57 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System.Net;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 显示信息
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void MessageEventHandler<TClient>(TClient client, MsgPermitEventArgs e);
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Connected
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TClient"></typeparam>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    public delegate Task ConnectedEventHandler<TClient>(TClient client, ConnectedEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 普通通知
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TClient"></typeparam>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void TouchSocketEventHandler<TClient>(TClient client, PluginEventArgs e);
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Connecting
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TClient"></typeparam>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    public delegate Task ConnectingEventHandler<TClient>(TClient client, ConnectingEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Id修改通知
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TClient"></typeparam>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void IdChangedEventHandler<TClient>(TClient client, IdChangedEventArgs e);
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 客户端断开连接
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TClient"></typeparam>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    public delegate Task DisconnectEventHandler<TClient>(TClient client, DisconnectEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Connecting
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TClient"></typeparam>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void ConnectingEventHandler<TClient>(TClient client, ConnectingEventArgs e);
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 显示信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    public delegate void MessageEventHandler<TClient>(TClient client, MsgPermitEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Connected
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TClient"></typeparam>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void ConnectedEventHandler<TClient>(TClient client, ConnectedEventArgs e);
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 接收数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    public delegate Task ReceivedEventHandler<TClient>(TClient client, ReceivedDataEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 客户端断开连接
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TClient"></typeparam>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <param name="e"></param>
 | 
			
		||||
public delegate void DisconnectEventHandler<TClient>(TClient client, DisconnectEventArgs e);
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 普通通知
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TClient"></typeparam>
 | 
			
		||||
    /// <param name="client"></param>
 | 
			
		||||
    /// <param name="e"></param>
 | 
			
		||||
    public delegate void TouchSocketEventHandler<TClient>(TClient client, PluginEventArgs e);
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 接收数据
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <param name="client"></param>
 | 
			
		||||
/// <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);
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Udp接收
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public delegate Task UdpReceivedEventHandler<TClient>(TClient client, UdpReceivedDataEventArgs e);
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -122,18 +122,39 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <inheritdoc cref="ITcpClient.Connect(int)"/>
 | 
			
		||||
        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);
 | 
			
		||||
            return client;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <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>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,18 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <inheritdoc cref="IService.Start"/>
 | 
			
		||||
        public static TService Start<TService>(this TService service, params IPHost[] iPHosts) where TService : ITcpService
 | 
			
		||||
        {
 | 
			
		||||
            service.Setup(new TouchSocketConfig()
 | 
			
		||||
                .SetListenIPHosts(iPHosts));
 | 
			
		||||
            TouchSocketConfig config;
 | 
			
		||||
            if (service.Config == null)
 | 
			
		||||
            {
 | 
			
		||||
                config = new TouchSocketConfig();
 | 
			
		||||
                config.SetListenIPHosts(iPHosts);
 | 
			
		||||
                service.Setup(config);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                config = service.Config;
 | 
			
		||||
                config.SetListenIPHosts(iPHosts);
 | 
			
		||||
            }
 | 
			
		||||
            service.Start();
 | 
			
		||||
            return service;
 | 
			
		||||
        }
 | 
			
		||||
@@ -35,8 +45,18 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <inheritdoc cref="IService.Start"/>
 | 
			
		||||
        public static TService Start<TService>(this TService service, IPHost iPHost) where TService : IUdpSession
 | 
			
		||||
        {
 | 
			
		||||
            service.Setup(new TouchSocketConfig()
 | 
			
		||||
                .SetBindIPHost(iPHost));
 | 
			
		||||
            TouchSocketConfig config;
 | 
			
		||||
            if (service.Config == null)
 | 
			
		||||
            {
 | 
			
		||||
                config = new TouchSocketConfig();
 | 
			
		||||
                config.SetBindIPHost(iPHost);
 | 
			
		||||
                service.Setup(config);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                config = service.Config;
 | 
			
		||||
                config.SetBindIPHost(iPHost);
 | 
			
		||||
            }
 | 
			
		||||
            service.Start();
 | 
			
		||||
            return service;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -44,14 +44,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        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>
 | 
			
		||||
        /// 数据处理适配器,默认为获取<see cref="UdpDataHandlingAdapter"/>
 | 
			
		||||
        /// 所需类型<see cref="Func{TResult}"/>
 | 
			
		||||
@@ -83,20 +75,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
            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>
 | 
			
		||||
        /// 设置(Udp系)数据处理适配器。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -30,16 +30,16 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IClient : IDependencyObject, IDisposable, ISocket
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取一个同步数据接收器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        IReceiver CreateReceiver();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理未经过适配器的数据。返回值表示是否继续向下传递。
 | 
			
		||||
        /// 移除同步数据接收器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理经过适配器后的数据。返回值表示是否继续向下传递。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
 | 
			
		||||
        void ClearReceiver();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 终端协议
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
using System.Net.Sockets;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
@@ -46,8 +45,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
 | 
			
		||||
        /// <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>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">数据缓存区</param>
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// TCP客户端终端接口
 | 
			
		||||
    /// Tcp客户端终端接口
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface ITcpClient : ITcpClientBase, IClientSender, IPluginObject
 | 
			
		||||
    {
 | 
			
		||||
@@ -65,12 +65,5 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <param name="config"></param>
 | 
			
		||||
        /// <exception cref="Exception"></exception>
 | 
			
		||||
        ITcpClient Setup(TouchSocketConfig config);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 配置服务器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="ipHost"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        ITcpClient Setup(string ipHost);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,13 +23,12 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using System.Net.Security;
 | 
			
		||||
using System.Net.Sockets;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// TCP终端基础接口。
 | 
			
		||||
    /// Tcp终端基础接口。
 | 
			
		||||
    /// <para>
 | 
			
		||||
    /// 注意:该接口并不仅表示客户端。<see cref="SocketClient"/>也实现了该接口。
 | 
			
		||||
    /// </para>
 | 
			
		||||
@@ -80,7 +79,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 判断是否在线
 | 
			
		||||
        /// <para>该属性仅表示TCP状态是否在线</para>
 | 
			
		||||
        /// <para>该属性仅表示Tcp状态是否在线</para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        bool Online { get; }
 | 
			
		||||
 | 
			
		||||
@@ -89,10 +88,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        int Port { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 接收模式
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReceiveType ReceiveType { get; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 使用Ssl加密
 | 
			
		||||
@@ -106,11 +102,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// <exception cref="Exception"></exception>
 | 
			
		||||
        void Close(string msg = TouchSocketCoreUtility.Empty);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取流,在正常模式下为<see cref="NetworkStream"/>,在Ssl模式下为<see cref="SslStream"/>。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        Stream GetStream();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置数据处理适配器
 | 
			
		||||
 
 | 
			
		||||
@@ -19,9 +19,6 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 即将断开连接(仅主动断开时有效)。
 | 
			
		||||
        /// <para>
 | 
			
		||||
        /// 当主动调用Close断开时。
 | 
			
		||||
        /// </para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="client"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,28 +10,27 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Http
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// IHttpPutPlugin
 | 
			
		||||
    /// IReceiver
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Obsolete("该插件已被弃用,请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
 | 
			
		||||
    public interface IHttpPutPlugin<in TClient> : IPlugin where TClient : IHttpSocketClient
 | 
			
		||||
    public interface IReceiver : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在收到Put时
 | 
			
		||||
        /// 异步等待并读取
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="client"></param>
 | 
			
		||||
        /// <param name="e"></param>
 | 
			
		||||
        /// <param name="token"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        Task OnHttpPut(TClient client, HttpContextEventArgs e);
 | 
			
		||||
    }
 | 
			
		||||
        Task<ReceiverResult> ReadAsync(CancellationToken token);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// IHttpPutPlugin
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Obsolete("该插件已被弃用,请考虑使用“IHttpPlugin”插件代替使用。本插件将在正式版发布时直接移除。", true)]
 | 
			
		||||
    public interface IHttpPutPlugin : IHttpPutPlugin<IHttpSocketClient>
 | 
			
		||||
    {
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 值异步等待并读取
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="token"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public ValueTask<ReceiverResult> ValueReadAsync(CancellationToken token);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,91 @@
 | 
			
		||||
#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.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Receiver
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Receiver : DisposableObject, IReceiver
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IClient m_client;
 | 
			
		||||
        private readonly AutoResetEvent m_resetEventForComplateRead = new AutoResetEvent(false);
 | 
			
		||||
        private readonly AsyncAutoResetEvent m_resetEventForRead = new AsyncAutoResetEvent(false);
 | 
			
		||||
        private ByteBlock m_byteBlock;
 | 
			
		||||
        private IRequestInfo m_requestInfo;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Receiver
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="client"></param>
 | 
			
		||||
        public Receiver(IClient client)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_client = client;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public async Task<ReceiverResult> ReadAsync(CancellationToken token)
 | 
			
		||||
        {
 | 
			
		||||
            this.ThrowIfDisposed();
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token);
 | 
			
		||||
            return new ReceiverResult(this.ComplateRead, this.m_byteBlock, this.m_requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public async ValueTask<ReceiverResult> ValueReadAsync(CancellationToken token)
 | 
			
		||||
        {
 | 
			
		||||
            this.ThrowIfDisposed();
 | 
			
		||||
            await this.m_resetEventForRead.WaitOneAsync(token);
 | 
			
		||||
            return new ReceiverResult(this.ComplateRead, this.m_byteBlock, this.m_requestInfo);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public bool TryInputReceive(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.DisposedValue)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            this.m_byteBlock = byteBlock;
 | 
			
		||||
            this.m_requestInfo = requestInfo;
 | 
			
		||||
            this.m_resetEventForRead.Set();
 | 
			
		||||
            if (byteBlock == null && requestInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.m_resetEventForComplateRead.WaitOne(TimeSpan.FromSeconds(10)))
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_client.ClearReceiver();
 | 
			
		||||
            this.m_resetEventForComplateRead.SafeDispose();
 | 
			
		||||
            this.m_resetEventForRead.SafeDispose();
 | 
			
		||||
            this.m_byteBlock = null;
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ComplateRead()
 | 
			
		||||
        {
 | 
			
		||||
            this.m_byteBlock = default;
 | 
			
		||||
            this.m_requestInfo = default;
 | 
			
		||||
            this.m_resetEventForComplateRead.Set();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// ReceiverResult
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public readonly struct ReceiverResult : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Action m_disAction;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// SocketReceiveResult
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="disAction"></param>
 | 
			
		||||
        /// <param name="byteBlock"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        public ReceiverResult(Action disAction, ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            this.m_disAction = disAction;
 | 
			
		||||
            this.ByteBlock = byteBlock;
 | 
			
		||||
            this.RequestInfo = requestInfo;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 字节块
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ByteBlock ByteBlock { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 数据对象
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IRequestInfo RequestInfo { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 连接已关闭
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsClosed => this.ByteBlock == null && this.RequestInfo == null;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            m_disAction?.Invoke();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 等待型客户端。
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IWaitingClient<TClient> : IWaitSender, IDisposable where TClient : IClient, IDefaultSender, ISender
 | 
			
		||||
    public interface IWaitingClient<TClient> : IWaitSender, IDisposable where TClient : IClient, ISender
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 等待设置。
 | 
			
		||||
 
 | 
			
		||||
@@ -30,18 +30,15 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public struct ResponsedData
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构造函数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="data"></param>
 | 
			
		||||
        /// <param name="requestInfo"></param>
 | 
			
		||||
        /// <param name="isRawBuffer"></param>
 | 
			
		||||
        public ResponsedData(byte[] data, IRequestInfo requestInfo, bool isRawBuffer)
 | 
			
		||||
        public ResponsedData(byte[] data, IRequestInfo requestInfo)
 | 
			
		||||
        {
 | 
			
		||||
            this.Data = data;
 | 
			
		||||
            this.RequestInfo = requestInfo;
 | 
			
		||||
            this.IsRawBuffer = isRawBuffer;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -53,10 +50,5 @@ namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
        /// RequestInfo
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IRequestInfo RequestInfo { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 是否为原生缓存区。即没有经过适配器处理。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsRawBuffer { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,353 +10,279 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets;
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权(除特别声明或在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
 | 
			
		||||
//  感谢您的下载和使用
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
internal class WaitingClient<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, IDefaultSender, ISender
 | 
			
		||||
namespace ThingsGateway.Foundation.Sockets
 | 
			
		||||
{
 | 
			
		||||
    private readonly Func<ResponsedData, bool> m_func;
 | 
			
		||||
    private readonly EasyLock easyLock = new();
 | 
			
		||||
    private readonly WaitData<ResponsedData> m_waitData = new();
 | 
			
		||||
    private readonly WaitDataAsync<ResponsedData> m_waitDataAsync = new();
 | 
			
		||||
 | 
			
		||||
    private volatile bool m_breaked;
 | 
			
		||||
 | 
			
		||||
    public WaitingClient(TClient client, WaitingOptions waitingOptions, Func<ResponsedData, bool> func)
 | 
			
		||||
    internal class WaitingClient<TClient> : DisposableObject, IWaitingClient<TClient> where TClient : IClient, ISender
 | 
			
		||||
    {
 | 
			
		||||
        this.Client = client ?? throw new ArgumentNullException(nameof(client));
 | 
			
		||||
        this.WaitingOptions = waitingOptions;
 | 
			
		||||
        this.m_func = func;
 | 
			
		||||
    }
 | 
			
		||||
        private readonly Func<ResponsedData, bool> m_func;
 | 
			
		||||
        private readonly SemaphoreSlim m_semaphoreSlim = new SemaphoreSlim(1, 1);
 | 
			
		||||
        private volatile bool m_breaked;
 | 
			
		||||
        private CancellationTokenSource m_cancellation;
 | 
			
		||||
 | 
			
		||||
    public WaitingClient(TClient client, WaitingOptions waitingOptions)
 | 
			
		||||
    {
 | 
			
		||||
        this.Client = client ?? throw new ArgumentNullException(nameof(client));
 | 
			
		||||
        this.WaitingOptions = waitingOptions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool CanSend
 | 
			
		||||
    {
 | 
			
		||||
        get
 | 
			
		||||
        public WaitingClient(TClient client, WaitingOptions waitingOptions, Func<ResponsedData, bool> func)
 | 
			
		||||
        {
 | 
			
		||||
            return this.Client is ITcpClientBase tcpClient ? tcpClient.CanSend : this.Client is IUdpSession;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public TClient Client { get; private set; }
 | 
			
		||||
 | 
			
		||||
    public WaitingOptions WaitingOptions { get; set; }
 | 
			
		||||
 | 
			
		||||
    protected override void Dispose(bool disposing)
 | 
			
		||||
    {
 | 
			
		||||
        this.Client = default;
 | 
			
		||||
        this.m_waitData.SafeDispose();
 | 
			
		||||
        this.m_waitDataAsync.SafeDispose();
 | 
			
		||||
        base.Dispose(disposing);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Cancel()
 | 
			
		||||
    {
 | 
			
		||||
        this.m_waitData.Cancel();
 | 
			
		||||
        this.m_waitDataAsync.Cancel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void OnDisconnected(ITcpClientBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        this.m_breaked = true;
 | 
			
		||||
        this.Cancel();
 | 
			
		||||
    }
 | 
			
		||||
    private void OnSerialSessionDisconnected(ISerialSessionBase client, DisconnectEventArgs e)
 | 
			
		||||
    {
 | 
			
		||||
        this.m_breaked = true;
 | 
			
		||||
        this.Cancel();
 | 
			
		||||
    }
 | 
			
		||||
    private bool OnHandleRawBuffer(ByteBlock byteBlock)
 | 
			
		||||
    {
 | 
			
		||||
        var responsedData = new ResponsedData(byteBlock.ToArray(), null, true);
 | 
			
		||||
        if (this.m_func == null || this.m_func.Invoke(responsedData))
 | 
			
		||||
        {
 | 
			
		||||
            return !this.Set(responsedData);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private bool OnHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
 | 
			
		||||
    {
 | 
			
		||||
        ResponsedData responsedData;
 | 
			
		||||
        if (byteBlock != null)
 | 
			
		||||
        {
 | 
			
		||||
            responsedData = new ResponsedData(byteBlock.ToArray(), requestInfo, false);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            responsedData = new ResponsedData(null, requestInfo, false);
 | 
			
		||||
            this.Client = client ?? throw new ArgumentNullException(nameof(client));
 | 
			
		||||
            this.WaitingOptions = waitingOptions;
 | 
			
		||||
            this.m_func = func;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.m_func == null || this.m_func.Invoke(responsedData))
 | 
			
		||||
        public WaitingClient(TClient client, WaitingOptions waitingOptions)
 | 
			
		||||
        {
 | 
			
		||||
            return !this.Set(responsedData);
 | 
			
		||||
            this.Client = client ?? throw new ArgumentNullException(nameof(client));
 | 
			
		||||
            this.WaitingOptions = waitingOptions;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
 | 
			
		||||
        public bool CanSend
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Reset()
 | 
			
		||||
    {
 | 
			
		||||
        this.m_waitData.Reset();
 | 
			
		||||
        this.m_waitDataAsync.Reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #region 同步Response
 | 
			
		||||
 | 
			
		||||
    public ResponsedData SendThenResponse(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            easyLock.Wait();
 | 
			
		||||
            this.m_breaked = false;
 | 
			
		||||
            this.Reset();
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                tcpClient.Disconnected += this.OnDisconnected;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
 | 
			
		||||
            {
 | 
			
		||||
                serialSession.Disconnected += this.OnSerialSessionDisconnected;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleReceivedData += this.OnHandleReceivedData;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleRawBuffer += this.OnHandleRawBuffer;
 | 
			
		||||
                return this.Client is ITcpClientBase tcpClient ? tcpClient.CanSend : this.Client is ISerialSessionBase serialSession ? serialSession.CanSend : this.Client is IUdpSession;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            if (this.WaitingOptions.RemoteIPHost != null && this.Client is IUdpSession session)
 | 
			
		||||
        public TClient Client { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public WaitingOptions WaitingOptions { get; set; }
 | 
			
		||||
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            this.Client = default;
 | 
			
		||||
            this.Cancel();
 | 
			
		||||
            base.Dispose(disposing);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Cancel()
 | 
			
		||||
        {
 | 
			
		||||
            this.m_cancellation.Cancel();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 同步Response
 | 
			
		||||
 | 
			
		||||
        public ResponsedData SendThenResponse(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
 | 
			
		||||
                this.m_semaphoreSlim.Wait();
 | 
			
		||||
                this.m_breaked = false;
 | 
			
		||||
                if (token.CanBeCanceled)
 | 
			
		||||
                {
 | 
			
		||||
                    session.Send(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
 | 
			
		||||
                    using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(timeout);
 | 
			
		||||
                    m_cancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, token);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    session.DefaultSend(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
 | 
			
		||||
                    m_cancellation = new CancellationTokenSource(timeout);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
 | 
			
		||||
                using (m_cancellation)
 | 
			
		||||
                {
 | 
			
		||||
                    this.Client.Send(buffer, offset, length);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    this.Client.DefaultSend(buffer, offset, length);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.m_waitData.SetCancellationToken(cancellationToken);
 | 
			
		||||
            switch (this.m_waitData.Wait(timeout))
 | 
			
		||||
            {
 | 
			
		||||
                case WaitDataStatus.SetRunning:
 | 
			
		||||
                    return this.m_waitData.WaitResult;
 | 
			
		||||
 | 
			
		||||
                case WaitDataStatus.Overtime:
 | 
			
		||||
                    throw new TimeoutException();
 | 
			
		||||
                case WaitDataStatus.Canceled:
 | 
			
		||||
                    if (this.WaitingOptions.RemoteIPHost != null && this.Client is IUdpSession session)
 | 
			
		||||
                    {
 | 
			
		||||
                        return this.WaitingOptions.ThrowBreakException && this.m_breaked ? throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。") : (ResponsedData)default;
 | 
			
		||||
                        using (var receiver = session.CreateReceiver())
 | 
			
		||||
                        {
 | 
			
		||||
                            session.Send(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
 | 
			
		||||
 | 
			
		||||
                            while (true)
 | 
			
		||||
                            {
 | 
			
		||||
                                using (var receiverResult = receiver.ReadAsync(m_cancellation.Token).GetFalseAwaitResult())
 | 
			
		||||
                                {
 | 
			
		||||
                                    var response = new ResponsedData(receiverResult.ByteBlock?.ToArray(), receiverResult.RequestInfo);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                case WaitDataStatus.Default:
 | 
			
		||||
                case WaitDataStatus.Disposed:
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new Exception("未知错误");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
 | 
			
		||||
            {
 | 
			
		||||
                tcpClient.Disconnected -= this.OnDisconnected;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
 | 
			
		||||
            {
 | 
			
		||||
                serialSession.Disconnected -= this.OnSerialSessionDisconnected;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleReceivedData -= this.OnHandleReceivedData;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleRawBuffer -= this.OnHandleRawBuffer;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public ResponsedData SendThenResponse(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenResponse(buffer, 0, buffer.Length, timeout, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ResponsedData SendThenResponse(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenResponse(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion 同步Response
 | 
			
		||||
 | 
			
		||||
    #region Response异步
 | 
			
		||||
 | 
			
		||||
    public async Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            await easyLock.WaitAsync();
 | 
			
		||||
            this.m_breaked = false;
 | 
			
		||||
            this.Reset();
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
 | 
			
		||||
            {
 | 
			
		||||
                tcpClient.Disconnected += this.OnDisconnected;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
 | 
			
		||||
            {
 | 
			
		||||
                serialSession.Disconnected += this.OnSerialSessionDisconnected;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleReceivedData += this.OnHandleReceivedData;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleRawBuffer += this.OnHandleRawBuffer;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.WaitingOptions.RemoteIPHost != null && this.Client is IUdpSession session)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
 | 
			
		||||
                {
 | 
			
		||||
                    session.Send(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    session.DefaultSend(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.SendAdapter)
 | 
			
		||||
                {
 | 
			
		||||
                    this.Client.Send(buffer, offset, length);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    this.Client.DefaultSend(buffer, offset, length);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.m_waitDataAsync.SetCancellationToken(cancellationToken);
 | 
			
		||||
            switch (await this.m_waitDataAsync.WaitAsync(timeout))
 | 
			
		||||
            {
 | 
			
		||||
                case WaitDataStatus.SetRunning:
 | 
			
		||||
                    return this.m_waitData.WaitResult;
 | 
			
		||||
 | 
			
		||||
                case WaitDataStatus.Overtime:
 | 
			
		||||
                    throw new TimeoutException();
 | 
			
		||||
                case WaitDataStatus.Canceled:
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        return this.WaitingOptions.ThrowBreakException && this.m_breaked ? throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。") : (ResponsedData)default;
 | 
			
		||||
                        using (var receiver = this.Client.CreateReceiver())
 | 
			
		||||
                        {
 | 
			
		||||
                            this.Client.Send(buffer, offset, length);
 | 
			
		||||
                            while (true)
 | 
			
		||||
                            {
 | 
			
		||||
                                using (var receiverResult = receiver.ReadAsync(m_cancellation.Token).GetFalseAwaitResult())
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (receiverResult.IsClosed)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        this.m_breaked = true;
 | 
			
		||||
                                        this.Cancel();
 | 
			
		||||
                                    }
 | 
			
		||||
                                    var response = new ResponsedData(receiverResult.ByteBlock?.ToArray(), receiverResult.RequestInfo);
 | 
			
		||||
 | 
			
		||||
                                    if (this.m_func == null)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        return response;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (this.m_func.Invoke(response))
 | 
			
		||||
                                        {
 | 
			
		||||
                                            return response;
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                case WaitDataStatus.Default:
 | 
			
		||||
                case WaitDataStatus.Disposed:
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new Exception("未知错误");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (OperationCanceledException)
 | 
			
		||||
            {
 | 
			
		||||
                return this.WaitingOptions.ThrowBreakException && this.m_breaked ? throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。") : throw new TimeoutException();
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.m_semaphoreSlim.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
 | 
			
		||||
        public ResponsedData SendThenResponse(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            easyLock.Release();
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ITcpClientBase tcpClient)
 | 
			
		||||
            return this.SendThenResponse(buffer, 0, buffer.Length, timeout, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ResponsedData SendThenResponse(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendThenResponse(byteBlock.Buffer, 0, byteBlock.Len, timeout, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 同步Response
 | 
			
		||||
 | 
			
		||||
        #region Response异步
 | 
			
		||||
 | 
			
		||||
        public async Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                tcpClient.Disconnected -= this.OnDisconnected;
 | 
			
		||||
                await this.m_semaphoreSlim.WaitAsync();
 | 
			
		||||
                this.m_breaked = false;
 | 
			
		||||
                if (token.CanBeCanceled)
 | 
			
		||||
                {
 | 
			
		||||
                    using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(timeout);
 | 
			
		||||
                    m_cancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, token);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    m_cancellation = new CancellationTokenSource(timeout);
 | 
			
		||||
                }
 | 
			
		||||
                using (m_cancellation)
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.WaitingOptions.RemoteIPHost != null && this.Client is IUdpSession session)
 | 
			
		||||
                    {
 | 
			
		||||
                        using (var receiver = session.CreateReceiver())
 | 
			
		||||
                        {
 | 
			
		||||
                            await session.SendAsync(this.WaitingOptions.RemoteIPHost.EndPoint, buffer, offset, length);
 | 
			
		||||
 | 
			
		||||
                            while (true)
 | 
			
		||||
                            {
 | 
			
		||||
                                using (var receiverResult = await receiver.ReadAsync(m_cancellation.Token))
 | 
			
		||||
                                {
 | 
			
		||||
                                    var response = new ResponsedData(receiverResult.ByteBlock?.ToArray(), receiverResult.RequestInfo);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        using (var receiver = this.Client.CreateReceiver())
 | 
			
		||||
                        {
 | 
			
		||||
                            await this.Client.SendAsync(buffer, offset, length);
 | 
			
		||||
                            while (true)
 | 
			
		||||
                            {
 | 
			
		||||
                                using (var receiverResult = await receiver.ReadAsync(m_cancellation.Token))
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (receiverResult.IsClosed)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        this.m_breaked = true;
 | 
			
		||||
                                        this.Cancel();
 | 
			
		||||
                                    }
 | 
			
		||||
                                    var response = new ResponsedData(receiverResult.ByteBlock?.ToArray(), receiverResult.RequestInfo);
 | 
			
		||||
 | 
			
		||||
                                    if (this.m_func == null)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        return response;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (this.m_func.Invoke(response))
 | 
			
		||||
                                        {
 | 
			
		||||
                                            return response;
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.BreakTrigger && this.Client is ISerialSessionBase serialSession)
 | 
			
		||||
            catch (OperationCanceledException)
 | 
			
		||||
            {
 | 
			
		||||
                serialSession.Disconnected -= this.OnSerialSessionDisconnected;
 | 
			
		||||
                return this.WaitingOptions.ThrowBreakException && this.m_breaked ? throw new Exception("等待已终止。可能是客户端已掉线,或者被注销。") : throw new TimeoutException();
 | 
			
		||||
            }
 | 
			
		||||
            if (this.WaitingOptions.AdapterFilter == AdapterFilter.AllAdapter || this.WaitingOptions.AdapterFilter == AdapterFilter.WaitAdapter)
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleReceivedData -= this.OnHandleReceivedData;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                this.Client.OnHandleRawBuffer -= this.OnHandleRawBuffer;
 | 
			
		||||
                this.m_semaphoreSlim.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendThenResponseAsync(buffer, 0, buffer.Length, timeout, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task<ResponsedData> SendThenResponseAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendThenResponseAsync(byteBlock.Buffer, 0, byteBlock.Len, timeout, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion Response异步
 | 
			
		||||
 | 
			
		||||
        #region 字节同步
 | 
			
		||||
 | 
			
		||||
        public byte[] SendThenReturn(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendThenResponse(buffer, offset, length, timeout, token).Data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public byte[] SendThenReturn(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendThenReturn(buffer, 0, buffer.Length, timeout, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public byte[] SendThenReturn(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return this.SendThenReturn(byteBlock.Buffer, 0, byteBlock.Len, timeout, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 字节同步
 | 
			
		||||
 | 
			
		||||
        #region 字节异步
 | 
			
		||||
 | 
			
		||||
        public async Task<byte[]> SendThenReturnAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return (await this.SendThenResponseAsync(buffer, offset, length, timeout, token)).Data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<byte[]> SendThenReturnAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return (await this.SendThenResponseAsync(buffer, 0, buffer.Length, timeout, token)).Data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<byte[]> SendThenReturnAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken token = default)
 | 
			
		||||
        {
 | 
			
		||||
            return (await this.SendThenResponseAsync(byteBlock.Buffer, 0, byteBlock.Len, timeout, token)).Data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion 字节异步
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Task<ResponsedData> SendThenResponseAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenResponseAsync(buffer, 0, buffer.Length, timeout, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Task<ResponsedData> SendThenResponseAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenResponseAsync(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion Response异步
 | 
			
		||||
 | 
			
		||||
    #region 字节同步
 | 
			
		||||
 | 
			
		||||
    public byte[] SendThenReturn(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenResponse(buffer, offset, length, timeout, cancellationToken).Data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public byte[] SendThenReturn(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenReturn(buffer, 0, buffer.Length, timeout, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public byte[] SendThenReturn(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return this.SendThenReturn(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion 字节同步
 | 
			
		||||
 | 
			
		||||
    #region 字节异步
 | 
			
		||||
 | 
			
		||||
    public async Task<byte[]> SendThenReturnAsync(byte[] buffer, int offset, int length, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return (await this.SendThenResponseAsync(buffer, offset, length, timeout, cancellationToken)).Data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<byte[]> SendThenReturnAsync(byte[] buffer, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return (await this.SendThenResponseAsync(buffer, 0, buffer.Length, timeout, cancellationToken)).Data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<byte[]> SendThenReturnAsync(ByteBlock byteBlock, int timeout = 1000 * 5, CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        return (await this.SendThenResponseAsync(byteBlock.Buffer, 0, byteBlock.Len, timeout, cancellationToken)).Data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion 字节异步
 | 
			
		||||
 | 
			
		||||
    private bool Set(ResponsedData responsedData)
 | 
			
		||||
    {
 | 
			
		||||
        this.m_waitData.Set(responsedData);
 | 
			
		||||
        this.m_waitDataAsync.Set(responsedData);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user