Files
ThingsGateway/framework/ThingsGateway.Foundation/DataHandleAdapter/ReadWriteDevicesTcpDataHandleAdapter.cs
T
2023-08-08 12:31:42 +08:00

152 lines
5.8 KiB
C#

#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 ThingsGateway.Foundation.Extension.Byte;
using ThingsGateway.Foundation.Extension.Generic;
namespace ThingsGateway.Foundation;
/// <summary>
/// TCP适配器基类
/// </summary>
public abstract class ReadWriteDevicesTcpDataHandleAdapter<TRequest> : CustomDataHandlingAdapter<TRequest> where TRequest : class, IMessage
{
/// <inheritdoc cref="ReadWriteDevicesTcpDataHandleAdapter{TRequest}"/>
public ReadWriteDevicesTcpDataHandleAdapter()
{
Request = GetInstance();
}
/// <inheritdoc/>
public override bool CanSendRequestInfo => false;
/// <inheritdoc/>
public override bool CanSplicingSend => false;
/// <inheritdoc/>
public virtual bool IsSendPackCommand { get; set; } = true;
/// <inheritdoc/>
public TRequest Request { get; set; }
/// <summary>
/// 发送前,对当前的命令进行打包处理
/// </summary>
public abstract byte[] PackCommand(byte[] command);
/// <inheritdoc/>
protected override FilterResult Filter(in ByteBlock byteBlock, bool beCached, ref TRequest request, ref int tempCapacity)
{
//获取全部内容
var allBytes = byteBlock.ToArray(0, byteBlock.Len);
Logger?.Trace(FoundationConst.LogMessageHeader + " - " + ThingsGatewayStatus.Received.GetDescription() + ":" + allBytes.ToHexString(" "));
//缓存/不缓存解析一样,因为游标已经归0
{
request = Request;
if (request.HeadBytesLength > byteBlock.CanReadLen)
{
return FilterResult.Cache;//当头部都无法解析时,直接缓存
}
var pos = byteBlock.Pos;//记录初始游标位置,防止本次无法解析时,回退游标。
byte[] header = new byte[] { };
if (request.HeadBytesLength > 0)
{
//当解析消息设定固定头长度大于0时,获取头部字节
byteBlock.Read(out header, request.HeadBytesLength);
}
//检查头部合法性
if (request.CheckHeadBytes(header))
{
if (request.BodyLength > byteBlock.CanReadLen)
{
//body不满足解析,开始缓存,然后保存对象
byteBlock.Pos = pos;//回退游标
request.ReceivedBytes = header;
return FilterResult.Cache;
}
if (request.BodyLength <= 0)
{
//如果body长度无法确定,直接读取全部
request.BodyLength = byteBlock.Len;
}
byteBlock.Read(out byte[] body, request.BodyLength);
var bytes = request.HeadBytes.SpliceArray(body);
return GetResponse(byteBlock, request, body, bytes);
}
else
{
byteBlock.Pos = byteBlock.Len;//移动游标
return FilterResult.GoOn;//放弃解析
}
}
}
/// <summary>
/// 获取泛型实例。
/// </summary>
/// <returns></returns>
protected abstract TRequest GetInstance();
/// <summary>
/// 解包获取实际数据包
/// <para>当不满足解析条件时,请返回<see cref="FilterResult.Cache"/>,此时会保存<see cref="ByteBlock.CanReadLen"/>的数据</para>
/// <para>当数据部分异常时,请移动<see cref="ByteBlock.Pos"/>到指定位置,然后返回<see cref="FilterResult.GoOn"/></para>
/// <para>当完全满足解析条件时,请返回<see cref="FilterResult.Success"/>最后将<see cref="ByteBlock.Pos"/>移至指定位置。</para>
/// </summary>
protected virtual FilterResult GetResponse(ByteBlock byteBlock, TRequest request, byte[] body, byte[] bytes)
{
var unpackbytes = UnpackResponse(request, request.SendBytes, body, bytes);
request.ReceivedBytes = bytes;
switch (unpackbytes)
{
case FilterResult.Cache:
return FilterResult.Cache;
case FilterResult.Success:
return FilterResult.Success;
case FilterResult.GoOn:
byteBlock.Pos = byteBlock.Len;
return FilterResult.GoOn;
default:
byteBlock.Pos = byteBlock.Len;
return FilterResult.GoOn;
}
}
/// <summary>
/// 发送方法,会重新建立<see cref="Request"/>
/// </summary>
protected void GoSend(byte[] item)
{
byte[] bytes;
if (IsSendPackCommand)
bytes = PackCommand(item);
else
bytes = item;
Request = GetInstance();
Request.SendBytes = bytes;
GoSend(bytes, 0, bytes.Length);
Logger?.Trace(FoundationConst.LogMessageHeader + " - " + ThingsGatewayStatus.Send.GetDescription() + ":" + Request.SendBytes.ToHexString(" "));
}
/// <inheritdoc/>
protected override void PreviewSend(byte[] buffer, int offset, int length)
{
GoSend(buffer);
}
/// <summary>
/// 报文拆包
/// </summary>
protected abstract FilterResult UnpackResponse(TRequest request, byte[] send, byte[] body, byte[] response);
}