diff --git a/src/Admin/README.md b/src/Admin/README.md
index dd1f01fdc..55e51fb36 100644
--- a/src/Admin/README.md
+++ b/src/Admin/README.md
@@ -1,5 +1,5 @@
-
ThingsBlazor
+ThingsBlazor
权限管理框架
diff --git a/src/Admin/ThingsGateway.Common/Options/WebsiteOptions.cs b/src/Admin/ThingsGateway.Common/Options/WebsiteOptions.cs
index f710ad0c5..6580c1694 100644
--- a/src/Admin/ThingsGateway.Common/Options/WebsiteOptions.cs
+++ b/src/Admin/ThingsGateway.Common/Options/WebsiteOptions.cs
@@ -28,6 +28,10 @@ public class WebsiteOptions : IConfigurableOptions
public bool Demo { get; set; }
public bool WebPageEnable { get; set; } = true;
+
+ public int MaxBlazorConnections { get; set; } = 5;
+ public bool BlazorConnectionLimitEnable { get; set; } = false;
+
///
/// 是否显示关于页面
///
diff --git a/src/Admin/ThingsGateway.DB/Services/SugarAopService/SugarAopService.cs b/src/Admin/ThingsGateway.DB/Services/SugarAopService/SugarAopService.cs
index e773a6e2a..b60dd8b5d 100644
--- a/src/Admin/ThingsGateway.DB/Services/SugarAopService/SugarAopService.cs
+++ b/src/Admin/ThingsGateway.DB/Services/SugarAopService/SugarAopService.cs
@@ -43,12 +43,12 @@ public class SugarAopService : ISugarAopService
}
if (sql.StartsWith("INSERT"))
{
- Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.ForegroundColor = ConsoleColor.Blue;
DbContext.WriteLog($"添加{config.ConfigId}库操作");
}
if (sql.StartsWith("DELETE"))
{
- Console.ForegroundColor = ConsoleColor.Red;
+ Console.ForegroundColor = ConsoleColor.Blue;
DbContext.WriteLog($"删除{config.ConfigId}库操作");
}
DbContext.WriteLogWithSql(UtilMethods.GetNativeSql(sql, pars));
diff --git a/src/Admin/ThingsGateway.Furion/ThingsGateway.Furion.csproj b/src/Admin/ThingsGateway.Furion/ThingsGateway.Furion.csproj
index f18235fd8..92227468e 100644
--- a/src/Admin/ThingsGateway.Furion/ThingsGateway.Furion.csproj
+++ b/src/Admin/ThingsGateway.Furion/ThingsGateway.Furion.csproj
@@ -31,6 +31,7 @@
+
@@ -43,6 +44,7 @@
+
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 545564233..4b1848922 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -1,11 +1,11 @@
- 10.9.70
- 10.9.70
- 10.9.70
- 2.9.28
- 10.9.25
+ 10.9.91
+ 10.9.91
+ 10.9.91
+ 2.9.29
+ 10.9.29
8.0.18
9.0.7
zh-Hans;en-US
diff --git a/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponent.razor.cs b/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponent.razor.cs
index f9055f663..67c638384 100644
--- a/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponent.razor.cs
+++ b/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponent.razor.cs
@@ -84,7 +84,7 @@ public partial class DeviceComponent : DeviceComponentBase
{
try
{
- var result1 = item.VariableRuntimes.PraseStructContent(Plc, result.Content, exWhenAny: true);
+ var result1 = item.VariableRuntimes.PraseStructContent(Plc, result.Content.Span, exWhenAny: true);
if (!result1.IsSuccess)
{
item.LastErrorMessage = result1.ErrorMessage;
diff --git a/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponentBase.cs b/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponentBase.cs
index 5986cfb18..2bdf6f72b 100644
--- a/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponentBase.cs
+++ b/src/Foundation/ThingsGateway.Foundation.Razor/DebugPages/DeviceComponentBase.cs
@@ -87,7 +87,7 @@ public abstract class DeviceComponentBase : ComponentBase, IDisposable
{
try
{
- var data = await Plc.ReadAsync(RegisterAddress, ArrayLength, DataType);
+ var data = await Plc.ReadArrayAsync(RegisterAddress, ArrayLength, DataType);
if (data.IsSuccess)
{
Plc.Logger?.LogInformation(data.Content.ToSystemTextJsonString());
@@ -111,7 +111,7 @@ public abstract class DeviceComponentBase : ComponentBase, IDisposable
{
try
{
- var data = await Plc.WriteAsync(RegisterAddress, WriteValue.GetJTokenFromString(), DataType);
+ var data = await Plc.WriteJTokenAsync(RegisterAddress, WriteValue.GetJTokenFromString(), DataType);
if (data.IsSuccess)
{
Plc.Logger?.LogInformation($" {WriteValue.GetJTokenFromString()} {Localizer["WriteSuccess"]}");
diff --git a/src/Foundation/ThingsGateway.Foundation.Variable/VariableObject.cs b/src/Foundation/ThingsGateway.Foundation.Variable/VariableObject.cs
index c71126ee0..768a74c73 100644
--- a/src/Foundation/ThingsGateway.Foundation.Variable/VariableObject.cs
+++ b/src/Foundation/ThingsGateway.Foundation.Variable/VariableObject.cs
@@ -83,7 +83,7 @@ public abstract class VariableObject
/// GetBytes
///
///
- public virtual byte[] GetBytes(Expression> accessor)
+ public virtual ReadOnlyMemory GetBytes(Expression> accessor)
{
if (accessor.Body == null)
{
@@ -107,8 +107,8 @@ public abstract class VariableObject
}
var func = accessor.Compile();
-
- return variable.VariableClass.ThingsGatewayBitConverter.GetBytesFormData(GetExpressionsValue(func(), variable), variable.VariableClass.DataType);
+ var data = GetExpressionsValue(func(), variable);
+ return variable.VariableClass.ThingsGatewayBitConverter.GetBytesFormData(data, variable.VariableClass.DataType, data is JArray jArray && jArray.Count > 1 ? true : false);
}
///
@@ -149,7 +149,7 @@ public abstract class VariableObject
var result = await Device.ReadAsync(item.RegisterAddress, item.Length, cancellationToken).ConfigureAwait(false);
if (result.IsSuccess)
{
- var result1 = item.VariableRuntimes.PraseStructContent(Device, result.Content, exWhenAny: true);
+ var result1 = item.VariableRuntimes.PraseStructContent(Device, result.Content.Span, exWhenAny: true);
if (!result1.IsSuccess)
{
item.LastErrorMessage = result1.ErrorMessage;
@@ -221,7 +221,7 @@ public abstract class VariableObject
JToken jToken = GetExpressionsValue(value, variableRuntimeProperty);
- var result = await Device.WriteAsync(variableRuntimeProperty.VariableClass.RegisterAddress, jToken, variableRuntimeProperty.VariableClass.DataType, cancellationToken).ConfigureAwait(false);
+ var result = await Device.WriteJTokenAsync(variableRuntimeProperty.VariableClass.RegisterAddress, jToken, variableRuntimeProperty.VariableClass.DataType, cancellationToken).ConfigureAwait(false);
return result;
}
catch (Exception ex)
diff --git a/src/Foundation/ThingsGateway.Foundation/Attributes/UriValidationAttribute.cs b/src/Foundation/ThingsGateway.Foundation/Attributes/UriValidationAttribute.cs
index 3e6d25fac..3efc1a448 100644
--- a/src/Foundation/ThingsGateway.Foundation/Attributes/UriValidationAttribute.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Attributes/UriValidationAttribute.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs b/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs
index 3a420c341..ea978a8ee 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptions.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptionsBase.cs b/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptionsBase.cs
index ce22deab9..4cecb3a41 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptionsBase.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/ChannelOptionsBase.cs
@@ -1,4 +1,4 @@
-// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPMessage.cs b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPMessage.cs
index 35198e48a..687c9b9fe 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPMessage.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPMessage.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -30,8 +30,8 @@ public abstract class DDPMessage : MessageBase, IResultMessage
public override bool CheckHead(ref TByteBlock byteBlock)
{
- var code = byteBlock.ReadByte();
- Type = byteBlock.ReadByte();
+ var code = ReaderExtension.ReadValue(ref byteBlock);
+ Type = ReaderExtension.ReadValue(ref byteBlock);
if (code != 0x7B)
{
@@ -44,15 +44,15 @@ public abstract class DDPMessage : MessageBase, IResultMessage
}
}
- public abstract int GetBodyLength(ref TByteBlock byteBlock) where TByteBlock : IByteBlock;
- public abstract byte[] GetContent(ref TByteBlock byteBlock) where TByteBlock : IByteBlock;
+ public abstract int GetBodyLength(ref TByteBlock byteBlock) where TByteBlock : IByteBlockReader;
+ public abstract byte[] GetContent(ref TByteBlock byteBlock) where TByteBlock : IByteBlockReader;
}
public class DDPTcpMessage : DDPMessage
{
public override int GetBodyLength(ref TByteBlock byteBlock)
{
- return byteBlock.ReadUInt16(EndianType.Big) - 4;
+ return ReaderExtension.ReadValue(ref byteBlock, EndianType.Big) - 4;
}
public override byte[] GetContent(ref TByteBlock byteBlock)
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPSend.cs b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPSend.cs
index 86dec4df3..e9031e80a 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPSend.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPSend.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -10,6 +10,8 @@
using System.Text;
+using ThingsGateway.NewLife.Extension;
+
namespace ThingsGateway.Foundation;
///
@@ -30,40 +32,37 @@ public class DDPSend : ISendMessage
Id = id;
Command = command;
}
- public void Build(ref TByteBlock byteBlock) where TByteBlock : IByteBlock
+ public void Build(ref TByteBlock byteBlock) where TByteBlock : IByteBlockWriter
{
- byteBlock.WriteByte(0x7b);
- byteBlock.WriteByte(Command);
- byteBlock.WriteUInt16(0x10, EndianType.Big);//len
- byteBlock.Write(PadTo11Byte(Id.Remove(0, 3)));
+ WriterExtension.WriteValue(ref byteBlock, (byte)0x7b);
+ WriterExtension.WriteValue(ref byteBlock, (byte)Command);
+ var id = PadTo11Byte(Id.Remove(0, 3));
if (Tcp)
{
- byteBlock.Write(ReadOnlyMemory.Span);
- byteBlock.WriteByte(0x7b);
- byteBlock.Position = 2;
- byteBlock.WriteUInt16((ushort)byteBlock.Length, EndianType.Big);//len
+ WriterExtension.WriteValue(ref byteBlock, (ushort)(id.Length + ReadOnlyMemory.Length + 3), EndianType.Big);//len
}
else
{
- byteBlock.WriteByte(0x7b);
+ WriterExtension.WriteValue(ref byteBlock, (ushort)0x10, EndianType.Big);//len
+ }
+ byteBlock.Write(id);
+ if (Tcp)
+ {
+ byteBlock.Write(ReadOnlyMemory.Span);
+ WriterExtension.WriteValue(ref byteBlock, (byte)0x7b);
+ }
+ else
+ {
+ WriterExtension.WriteValue(ref byteBlock, (byte)0x7b);
byteBlock.Write(ReadOnlyMemory.Span);
}
}
private static byte[] PadTo11Byte(string id)
{
- var bytes = Encoding.UTF8.GetBytes(id);
-
- if (bytes.Length < 11)
- {
- byte[] newBytes = new byte[11];
- Array.Copy(bytes, newBytes, bytes.Length);
- for (int i = bytes.Length; i < 11; i++)
- {
- newBytes[i] = 0;
- }
- return newBytes;
- }
- return bytes;
+ var buffer = new byte[11];
+ var str = id.AsSpan();
+ int byteCount = Encoding.UTF8.GetBytes(str.Slice(0, Math.Min(str.Length, 11)), buffer);
+ return buffer;
}
}
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPTcpSessionClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPTcpSessionClientChannel.cs
index 8879e4907..bceca25f8 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPTcpSessionClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPTcpSessionClientChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -42,17 +42,17 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
DataHandlingAdapter.SendAsyncCallBack = DefaultSendAsync;
return base.OnTcpConnected(e);
}
- protected Task DefaultSendAsync(ReadOnlyMemory memory)
+ protected Task DefaultSendAsync(ReadOnlyMemory memory, CancellationToken cancellationToken)
{
- return DDPAdapter.SendInputAsync(new DDPSend(memory, Id, true));
+ return DDPAdapter.SendInputAsync(new DDPSend(memory, Id, true), cancellationToken);
}
- protected Task DDPSendAsync(ReadOnlyMemory memory)
+ protected Task DDPSendAsync(ReadOnlyMemory memory, CancellationToken cancellationToken)
{
- return base.ProtectedDefaultSendAsync(memory);
+ return base.ProtectedDefaultSendAsync(memory, cancellationToken);
}
private DDPMessage DDPMessage { get; set; }
- private Task DDPHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
+ private Task DDPHandleReceivedData(IByteBlockReader byteBlock, IRequestInfo requestInfo)
{
if (requestInfo is DDPMessage dDPMessage)
DDPMessage = dDPMessage;
@@ -62,13 +62,14 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
private DeviceSingleStreamDataHandleAdapter DDPAdapter = new();
private WaitLock _waitLock = new(nameof(DDPTcpSessionClientChannel));
- protected override async ValueTask OnTcpReceiving(ByteBlock byteBlock)
+
+ protected override async ValueTask OnTcpReceiving(IByteBlockReader byteBlock)
{
DDPMessage? message = null;
try
{
await _waitLock.WaitAsync().ConfigureAwait(false);
- await DDPAdapter.ReceivedInputAsync(byteBlock).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ await DDPAdapter.ReceivedInputAsync(byteBlock).ConfigureAwait(false);
message = DDPMessage;
DDPMessage = null;
@@ -85,9 +86,18 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
var id = $"ID={message.Id}";
if (message.Type == 0x09)
{
- byteBlock.Reset();
- byteBlock.Write(message.Content);
- return false;
+ var reader = new ByteBlockReader(message.Content);
+
+ if (this.DataHandlingAdapter == null)
+ {
+ await this.OnTcpReceived(new ReceivedDataEventArgs(reader, default)).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ }
+ else
+ {
+ await this.DataHandlingAdapter.ReceivedInputAsync(reader).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ }
+
+ return true;
}
else
{
@@ -102,7 +112,7 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
Logger?.Debug($"Old socket connections with the same ID {id} will be closed");
try
{
- await oldClient.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
+ //await oldClient.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
await oldClient.CloseAsync().ConfigureAwait(false);
}
catch
@@ -120,13 +130,13 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
await ResetIdAsync(id).ConfigureAwait(false);
//发送成功
- await DDPAdapter.SendInputAsync(new DDPSend(ReadOnlyMemory.Empty, id, true, 0x81)).ConfigureAwait(false);
+ await DDPAdapter.SendInputAsync(new DDPSend(ReadOnlyMemory.Empty, id, true, 0x81), ClosedToken).ConfigureAwait(false);
if (log)
Logger?.Info(string.Format(AppResource.DtuConnected, Id));
}
else if (message.Type == 0x02)
{
- await DDPAdapter.SendInputAsync(new DDPSend(ReadOnlyMemory.Empty, Id, true, 0x82)).ConfigureAwait(false);
+ await DDPAdapter.SendInputAsync(new DDPSend(ReadOnlyMemory.Empty, Id, true, 0x82), ClosedToken).ConfigureAwait(false);
Logger?.Info(string.Format(AppResource.DtuDisconnecting, Id));
await Task.Delay(100).ConfigureAwait(false);
await this.CloseAsync().ConfigureAwait(false);
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPUdpSessionChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPUdpSessionChannel.cs
index cbbfa199a..de60b15b7 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPUdpSessionChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/DDP/DDPUdpSessionChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -49,11 +49,12 @@ public class DDPUdpSessionChannel : UdpSessionChannel, IClientChannel, IDtuUdpSe
DataHandlingAdapter.SendCallBackAsync = DefaultSendAsync;
}
- protected Task DefaultSendAsync(EndPoint endPoint, ReadOnlyMemory memory)
+
+ protected Task DefaultSendAsync(EndPoint endPoint, ReadOnlyMemory memory, CancellationToken token)
{
if (TryGetId(endPoint, out var id))
{
- return DDPAdapter.SendInputAsync(endPoint, new DDPSend(memory, id, false));
+ return DDPAdapter.SendInputAsync(endPoint, new DDPSend(memory, id, false), token);
}
else
{
@@ -61,14 +62,14 @@ public class DDPUdpSessionChannel : UdpSessionChannel, IClientChannel, IDtuUdpSe
}
}
- protected Task DDPSendAsync(EndPoint endPoint, ReadOnlyMemory memory)
+ protected Task DDPSendAsync(EndPoint endPoint, ReadOnlyMemory memory, CancellationToken token)
{
//获取endpoint
- return base.ProtectedDefaultSendAsync(endPoint, memory);
+ return base.ProtectedDefaultSendAsync(endPoint, memory, token);
}
private ConcurrentDictionary DDPMessageDict { get; set; } = new();
- private Task DDPHandleReceivedData(EndPoint endPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
+ private Task DDPHandleReceivedData(EndPoint endPoint, IByteBlockReader byteBlock, IRequestInfo requestInfo)
{
if (requestInfo is DDPMessage dDPMessage)
{
@@ -126,9 +127,18 @@ public class DDPUdpSessionChannel : UdpSessionChannel, IClientChannel, IDtuUdpSe
var id = $"ID={message.Id}";
if (message.Type == 0x09)
{
- byteBlock.Reset();
- byteBlock.Write(message.Content);
- return false;
+ var reader = new ByteBlockReader(message.Content);
+
+ if (this.DataHandlingAdapter == null)
+ {
+ await this.OnUdpReceived(new UdpReceivedDataEventArgs(endPoint, reader, default)).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ }
+ else
+ {
+ await this.DataHandlingAdapter.ReceivedInput(endPoint, reader).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ }
+
+ return true;
}
else
{
@@ -155,13 +165,13 @@ public class DDPUdpSessionChannel : UdpSessionChannel, IClientChannel, IDtuUdpSe
}
//发送成功
- await DDPAdapter.SendInputAsync(endPoint, new DDPSend(ReadOnlyMemory.Empty, id, false, 0x81)).ConfigureAwait(false);
+ await DDPAdapter.SendInputAsync(endPoint, new DDPSend(ReadOnlyMemory.Empty, id, false, 0x81), ClosedToken).ConfigureAwait(false);
if (log)
Logger?.Info(string.Format(AppResource.DtuConnected, id));
}
else if (message.Type == 0x02)
{
- await DDPAdapter.SendInputAsync(endPoint, new DDPSend(ReadOnlyMemory.Empty, id, false, 0x82)).ConfigureAwait(false);
+ await DDPAdapter.SendInputAsync(endPoint, new DDPSend(ReadOnlyMemory.Empty, id, false, 0x82), ClosedToken).ConfigureAwait(false);
Logger?.Info(string.Format(AppResource.DtuDisconnecting, id));
await Task.Delay(100).ConfigureAwait(false);
IdDict.TryRemove(endPoint, out _);
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/DtuSeviceType.cs b/src/Foundation/ThingsGateway.Foundation/Channel/DtuSeviceType.cs
index 9ea4aba0c..d30ef9c4c 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/DtuSeviceType.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/DtuSeviceType.cs
@@ -1,4 +1,4 @@
-// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/Extension/ChannelOptionsExtensions.cs b/src/Foundation/ThingsGateway.Foundation/Channel/Extension/ChannelOptionsExtensions.cs
index 996855d64..75d50956a 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/Extension/ChannelOptionsExtensions.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/Extension/ChannelOptionsExtensions.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/IChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/IChannel.cs
index 7cfa212a8..5c1543939 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/IChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/IChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -37,10 +37,7 @@ public interface IChannel : ISetupConfigObject, IDisposable, IClosableClient, IC
///
public ConcurrentList Collects { get; }
- ///
- /// MaxSign
- ///
- int MaxSign { get; set; }
+
///
/// 通道启动成功后
@@ -66,6 +63,11 @@ public interface IChannel : ISetupConfigObject, IDisposable, IClosableClient, IC
/// 主动请求时的等待池
///
public ConcurrentDictionary> ChannelReceivedWaitDict { get; }
+
+ void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue);
+
+
+
}
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs b/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs
index 329155efe..e0209c982 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/IChannelOptions.cs
@@ -1,4 +1,4 @@
-// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs
index 10e163310..304dd272f 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/IClientChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/IDtuUdpSessionChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/IDtuUdpSessionChannel.cs
index 996c3c9ad..d183170d6 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/IDtuUdpSessionChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/IDtuUdpSessionChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/ITcpServiceChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/ITcpServiceChannel.cs
index 75b292050..0e00165b5 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/ITcpServiceChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/ITcpServiceChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs
index 9af79995c..33b309d6d 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/OtherChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -12,6 +12,8 @@ using System.Collections.Concurrent;
using ThingsGateway.NewLife;
+using TouchSocket.SerialPorts;
+
namespace ThingsGateway.Foundation;
///
@@ -25,15 +27,17 @@ public class OtherChannel : SetupConfigObject, IClientChannel
public OtherChannel(IChannelOptions channelOptions)
{
ChannelOptions = channelOptions;
-
- WaitHandlePool.MaxSign = ushort.MaxValue;
}
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
- ///
- public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
-
+ public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
+ {
+ var pool = WaitHandlePool;
+ WaitHandlePool = new WaitHandlePool(minSign, maxSign);
+ pool?.CancelAll();
+ pool?.SafeDispose();
+ }
///
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
@@ -60,7 +64,7 @@ public class OtherChannel : SetupConfigObject, IClientChannel
///
/// 等待池
///
- public WaitHandlePool WaitHandlePool { get; } = new();
+ public WaitHandlePool WaitHandlePool { get; internal set; } = new();
///
public WaitLock WaitLock => ChannelOptions.WaitLock;
@@ -109,7 +113,7 @@ public class OtherChannel : SetupConfigObject, IClientChannel
m_dataHandlingAdapter = adapter;
}
- private async Task PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
+ private async Task PrivateHandleReceivedData(IByteBlockReader byteBlock, IRequestInfo requestInfo)
{
LastReceivedTime = DateTime.Now;
await this.OnChannelReceivedEvent(new ReceivedDataEventArgs(byteBlock, requestInfo), ChannelReceived).ConfigureAwait(false);
@@ -119,8 +123,9 @@ public class OtherChannel : SetupConfigObject, IClientChannel
/// 异步发送数据,保护方法。
///
/// 待发送的字节数据内存。
+ /// cancellationToken
/// 异步任务。
- protected Task ProtectedDefaultSendAsync(ReadOnlyMemory memory)
+ protected Task ProtectedDefaultSendAsync(ReadOnlyMemory memory, CancellationToken cancellationToken)
{
LastSentTime = DateTime.Now;
return Task.CompletedTask;
@@ -134,77 +139,58 @@ public class OtherChannel : SetupConfigObject, IClientChannel
public bool IsClient => true;
- public bool Online => true;
-
+ public bool Online => online;
+ public CancellationToken ClosedToken => this.m_transport == null ? new CancellationToken(true) : this.m_transport.Token;
+ private CancellationTokenSource m_transport;
public Task CloseAsync(string msg, CancellationToken token)
{
+ var cts = m_transport;
+ m_transport = null;
+ cts?.SafeCancel();
+ cts?.SafeDispose();
+ online = false;
+
return Task.FromResult(Result.Success);
}
-
+ public volatile bool online;
public Task ConnectAsync(int millisecondsTimeout, CancellationToken token)
{
+ var cts = m_transport;
+ m_transport = new();
+ cts?.SafeCancel();
+ cts?.SafeDispose();
+ online = true;
+ if (this.m_dataHandlingAdapter == null)
+ {
+ var adapter = this.Config.GetValue(SerialPortConfigExtension.SerialDataHandlingAdapterProperty)?.Invoke();
+ if (adapter != null)
+ {
+ this.SetAdapter(adapter);
+ }
+ }
return Task.CompletedTask;
}
- public async Task SendAsync(IList> transferBytes)
- {
- // 检查数据处理适配器是否存在且支持拼接发送
- if (m_dataHandlingAdapter?.CanSplicingSend != true)
- {
- // 如果不支持拼接发送,则计算所有字节片段的总长度
- var length = 0;
- foreach (var item in transferBytes)
- {
- length += item.Count;
- }
- // 使用计算出的总长度创建一个连续的内存块
- using (var byteBlock = new ByteBlock(length))
- {
- // 将每个字节片段写入连续的内存块
- foreach (var item in transferBytes)
- {
- byteBlock.Write(new ReadOnlySpan(item.Array, item.Offset, item.Count));
- }
- // 根据数据处理适配器的存在与否,选择不同的发送方式
- if (m_dataHandlingAdapter == null)
- {
- // 如果没有数据处理适配器,则使用默认方式发送
- await ProtectedDefaultSendAsync(byteBlock.Memory).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
- }
- else
- {
- // 如果有数据处理适配器,则通过适配器发送
- await m_dataHandlingAdapter.SendInputAsync(byteBlock.Memory).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
- }
- }
- }
- else
- {
- // 如果数据处理适配器支持拼接发送,则直接发送字节列表
- await m_dataHandlingAdapter.SendInputAsync(transferBytes).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
- }
- }
-
- public Task SendAsync(ReadOnlyMemory memory)
+ public Task SendAsync(ReadOnlyMemory memory, CancellationToken cancellationToken)
{
if (m_dataHandlingAdapter == null)
{
- return ProtectedDefaultSendAsync(memory);
+ return ProtectedDefaultSendAsync(memory, cancellationToken);
}
else
{
// 否则,使用适配器的发送方法进行数据发送。
- return m_dataHandlingAdapter.SendInputAsync(memory);
+ return m_dataHandlingAdapter.SendInputAsync(memory, cancellationToken);
}
}
- public Task SendAsync(IRequestInfo requestInfo)
+ public Task SendAsync(IRequestInfo requestInfo, CancellationToken cancellationToken)
{
// 检查是否具备发送请求的条件,如果不具备则抛出异常
ThrowIfCannotSendRequestInfo();
// 使用数据处理适配器异步发送输入请求
- return m_dataHandlingAdapter.SendInputAsync(requestInfo);
+ return m_dataHandlingAdapter.SendInputAsync(requestInfo, cancellationToken);
}
private void ThrowIfCannotSendRequestInfo()
{
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/DtuPlugin.cs b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/DtuPlugin.cs
index 6d38bd69b..b2554d580 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/DtuPlugin.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/DtuPlugin.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -31,13 +31,13 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
{
_heartbeat = value;
if (!heartbeatHex)
- HeartbeatByte = new ArraySegment(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
+ HeartbeatByte = (Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
else
- HeartbeatByte = new ArraySegment(_heartbeat?.HexStringToBytes() ?? Array.Empty());
+ HeartbeatByte = (_heartbeat?.HexStringToBytes() ?? Array.Empty());
}
}
private string _heartbeat;
- private ArraySegment HeartbeatByte = new();
+ private Memory HeartbeatByte = new();
private bool heartbeatHex;
@@ -51,9 +51,9 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
{
heartbeatHex = value;
if (!heartbeatHex)
- HeartbeatByte = new ArraySegment(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
+ HeartbeatByte = (Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
else
- HeartbeatByte = new ArraySegment(_heartbeat?.HexStringToBytes() ?? Array.Empty());
+ HeartbeatByte = (_heartbeat?.HexStringToBytes() ?? Array.Empty());
}
}
public bool DtuIdHex { get; set; }
@@ -61,7 +61,7 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
///
public async Task OnTcpReceiving(ITcpSession client, ByteBlockEventArgs e)
{
- var len = HeartbeatByte.Count;
+ var len = HeartbeatByte.Length;
if (client is TcpSessionClientChannel socket && socket.Service is ITcpServiceChannel tcpServiceChannel)
{
if (!socket.Id.StartsWith("ID="))
@@ -71,7 +71,7 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
{
try
{
- await oldClient.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
+ //await oldClient.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
await oldClient.CloseAsync().ConfigureAwait(false);
oldClient.Dispose();
}
@@ -88,7 +88,7 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
{
try
{
- await socket.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
+ //await socket.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
await socket.CloseAsync().ConfigureAwait(false);
socket.Dispose();
}
@@ -102,14 +102,14 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
if (len > 0)
{
- if (HeartbeatByte.SequenceEqual(e.ByteBlock.AsSegment(0, len)))
+ if (HeartbeatByte.Span.SequenceEqual(e.ByteBlock.Memory.Slice(0, len).Span))
{
if (DateTimeOffset.Now - socket.LastSentTime < TimeSpan.FromMilliseconds(200))
{
await Task.Delay(200).ConfigureAwait(false);
}
//回应心跳包
- await socket.SendAsync(HeartbeatByte).ConfigureAwait(false);
+ await socket.SendAsync(HeartbeatByte, socket.ClosedToken).ConfigureAwait(false);
e.Handled = true;
if (socket.Logger?.LogLevel <= LogLevel.Trace)
socket.Logger?.Trace($"{socket}- Heartbeat");
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/HeartbeatAndReceivePlugin.cs b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/HeartbeatAndReceivePlugin.cs
index f1c96f211..79de2a901 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/HeartbeatAndReceivePlugin.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/HeartbeatAndReceivePlugin.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -15,7 +15,7 @@ using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Foundation;
[PluginOption(Singleton = true)]
-internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugin, ITcpReceivingPlugin, ITcpClosingPlugin
+internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugin, ITcpReceivingPlugin, ITcpClosedPlugin
{
public string DtuId
{
@@ -27,13 +27,13 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
{
_dtuId = value;
if (!dtuIdHex)
- DtuIdByte = new ArraySegment(Encoding.UTF8.GetBytes(_dtuId ?? string.Empty));
+ DtuIdByte = (Encoding.UTF8.GetBytes(_dtuId ?? string.Empty));
else
- DtuIdByte = new ArraySegment(_dtuId?.HexStringToBytes() ?? Array.Empty());
+ DtuIdByte = (_dtuId?.HexStringToBytes() ?? Array.Empty());
}
}
private string _dtuId;
- private ArraySegment DtuIdByte;
+ private Memory DtuIdByte;
///
/// 心跳字符串
@@ -48,13 +48,13 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
{
_heartbeat = value;
if (!heartbeatHex)
- HeartbeatByte = new ArraySegment(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
+ HeartbeatByte = (Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
else
- HeartbeatByte = new ArraySegment(_heartbeat?.HexStringToBytes() ?? Array.Empty());
+ HeartbeatByte = (_heartbeat?.HexStringToBytes() ?? Array.Empty());
}
}
private string _heartbeat;
- private ArraySegment HeartbeatByte;
+ private Memory HeartbeatByte;
@@ -73,12 +73,12 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
heartbeatHex = value;
if (!heartbeatHex)
{
- HeartbeatByte = new ArraySegment(Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
+ HeartbeatByte = (Encoding.UTF8.GetBytes(_heartbeat ?? string.Empty));
}
else
{
- HeartbeatByte = new ArraySegment(_heartbeat?.HexStringToBytes() ?? Array.Empty());
+ HeartbeatByte = (_heartbeat?.HexStringToBytes() ?? Array.Empty());
}
}
@@ -95,12 +95,12 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
dtuIdHex = value;
if (!dtuIdHex)
{
- DtuIdByte = new ArraySegment(Encoding.UTF8.GetBytes(_dtuId ?? string.Empty));
+ DtuIdByte = (Encoding.UTF8.GetBytes(_dtuId ?? string.Empty));
}
else
{
- DtuIdByte = new ArraySegment(_dtuId?.HexStringToBytes() ?? Array.Empty());
+ DtuIdByte = (_dtuId?.HexStringToBytes() ?? Array.Empty());
}
}
@@ -123,7 +123,7 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
if (client is ITcpClient tcpClient)
{
- await tcpClient.SendAsync(DtuIdByte).ConfigureAwait(false);
+ await tcpClient.SendAsync(DtuIdByte, tcpClient.ClosedToken).ConfigureAwait(false);
if (Task == null)
{
@@ -145,7 +145,7 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
await Task.Delay(200).ConfigureAwait(false);
}
- await tcpClient.SendAsync(HeartbeatByte).ConfigureAwait(false);
+ await tcpClient.SendAsync(HeartbeatByte, tcpClient.ClosedToken).ConfigureAwait(false);
tcpClient.Logger?.Trace($"{tcpClient}- Heartbeat");
failedCount = 0;
}
@@ -178,10 +178,10 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
if (client is ITcpClient tcpClient)
{
- var len = HeartbeatByte.Count;
+ var len = HeartbeatByte.Length;
if (len > 0)
{
- if (HeartbeatByte.SequenceEqual(e.ByteBlock.AsSegment(0, len)))
+ if (HeartbeatByte.Span.SequenceEqual(e.ByteBlock.Memory.Slice(0, len).Span))
{
e.Handled = true;
}
@@ -190,7 +190,7 @@ internal sealed class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugi
}
}
- public Task OnTcpClosing(ITcpSession client, ClosingEventArgs e)
+ public Task OnTcpClosed(ITcpSession client, ClosedEventArgs e)
{
SendHeartbeat = false;
return EasyTask.CompletedTask;
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/IDtu.cs b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/IDtu.cs
index 54a1399d0..dbf5cc3fe 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/IDtu.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/IDtu.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/PluginUtil.cs b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/PluginUtil.cs
index f8325b213..3b869e868 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/PluginUtil.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/Plugin/PluginUtil.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -79,7 +79,7 @@ public static class PluginUtil
.SetTick(TimeSpan.FromMilliseconds(channelOptions.CheckClearTime))
.SetOnClose(async (c, t) =>
{
- await c.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
+ //await c.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
await c.CloseAsync($"{channelOptions.CheckClearTime}ms Timeout").ConfigureAwait(false);
});
};
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs
index a234bc9b7..b1fd058e1 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/SerialPortChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -24,15 +24,17 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
public SerialPortChannel(IChannelOptions channelOptions)
{
ChannelOptions = channelOptions;
-
- WaitHandlePool.MaxSign = ushort.MaxValue;
}
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
- ///
- public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
-
+ public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
+ {
+ var pool = WaitHandlePool;
+ WaitHandlePool = new WaitHandlePool(minSign, maxSign);
+ pool?.CancelAll();
+ pool?.SafeDispose();
+ }
///
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
@@ -62,7 +64,7 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
///
/// 等待池
///
- public WaitHandlePool WaitHandlePool { get; } = new();
+ public WaitHandlePool WaitHandlePool { get; internal set; } = new();
///
public WaitLock WaitLock => ChannelOptions.WaitLock;
@@ -82,6 +84,7 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
//await _connectLock.WaitAsync().ConfigureAwait(false);
if (Online)
{
+ PortName = null;
var result = await base.CloseAsync(msg, token).ConfigureAwait(false);
if (!Online)
{
@@ -99,7 +102,7 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
}
///
- public new async Task ConnectAsync(int millisecondsTimeout, CancellationToken token)
+ public override async Task ConnectAsync(int millisecondsTimeout, CancellationToken token)
{
if (!Online)
{
@@ -109,6 +112,12 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
if (!Online)
{
if (token.IsCancellationRequested) return;
+
+
+ var port = Config?.GetValue(SerialPortConfigExtension.SerialPortOptionProperty);
+ if (port != null)
+ PortName = $"{port.PortName}";
+
await base.ConnectAsync(millisecondsTimeout, token).ConfigureAwait(false);
if (Online)
{
@@ -130,20 +139,16 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
if (adapter is SingleStreamDataHandlingAdapter singleStreamDataHandlingAdapter)
SetAdapter(singleStreamDataHandlingAdapter);
}
-
+ private string PortName { get; set; }
///
public override string? ToString()
{
- if (ProtectedMainSerialPort != null)
- {
- return $"{ProtectedMainSerialPort.PortName}";
- }
- else
- {
- var port = Config?.GetValue(SerialPortConfigExtension.SerialPortOptionProperty);
- if (port != null)
- return $"{port.PortName}";
- }
+ if (!PortName.IsNullOrEmpty())
+ return PortName;
+
+ var port = Config?.GetValue(SerialPortConfigExtension.SerialPortOptionProperty);
+ if (port != null)
+ return $"{port.PortName}";
return base.ToString();
}
@@ -192,9 +197,9 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
}
///
- protected override void Dispose(bool disposing)
+ protected override void SafetyDispose(bool disposing)
{
WaitHandlePool.SafeDispose();
- base.Dispose(disposing);
+ base.SafetyDispose(disposing);
}
}
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs
index 00fd6e396..c4e0985fd 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/TcpClientChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -24,10 +24,15 @@ public class TcpClientChannel : TcpClient, IClientChannel
{
ChannelOptions = channelOptions;
- WaitHandlePool.MaxSign = ushort.MaxValue;
}
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
- public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
+ public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
+ {
+ var pool = WaitHandlePool;
+ WaitHandlePool = new WaitHandlePool(minSign, maxSign);
+ pool?.CancelAll();
+ pool?.SafeDispose();
+ }
///
public ChannelReceivedEventHandler ChannelReceived { get; } = new();
@@ -57,7 +62,7 @@ public class TcpClientChannel : TcpClient, IClientChannel
///
/// 等待池
///
- public WaitHandlePool WaitHandlePool { get; } = new();
+ public WaitHandlePool WaitHandlePool { get; internal set; } = new();
public virtual WaitLock GetLock(string key) => WaitLock;
///
@@ -181,9 +186,9 @@ public class TcpClientChannel : TcpClient, IClientChannel
}
///
- protected override void Dispose(bool disposing)
+ protected override void SafetyDispose(bool disposing)
{
WaitHandlePool.SafeDispose();
- base.Dispose(disposing);
+ base.SafetyDispose(disposing);
}
}
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs
index 7be512e6c..e37b624ab 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/TcpServiceChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -23,10 +23,10 @@ public abstract class TcpServiceChannelBase : TcpService, ITcp
///
public ConcurrentList Collects { get; } = new();
- ///
- /// 停止时是否发送ShutDown
- ///
- public bool ShutDownEnable { get; set; } = true;
+ /////
+ ///// 停止时是否发送ShutDown
+ /////
+ //public bool ShutDownEnable { get; set; } = true;
///
public override async Task ClearAsync()
@@ -35,8 +35,8 @@ public abstract class TcpServiceChannelBase : TcpService, ITcp
{
try
{
- if (ShutDownEnable)
- await client.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
+ //if (ShutDownEnable)
+ // await client.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
await client.CloseAsync().ConfigureAwait(false);
client.SafeDispose();
@@ -51,8 +51,8 @@ public abstract class TcpServiceChannelBase : TcpService, ITcp
{
if (this.TryGetClient(id, out var client))
{
- if (ShutDownEnable)
- await client.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
+ //if (ShutDownEnable)
+ // await client.ShutdownAsync(System.Net.Sockets.SocketShutdown.Both).ConfigureAwait(false);
await client.CloseAsync().ConfigureAwait(false);
client.SafeDispose();
}
@@ -85,6 +85,10 @@ public abstract class TcpServiceChannelBase : TcpService, ITcp
}
finally
{
+ var cts = m_transport;
+ m_transport = new();
+ cts?.SafeCancel();
+ cts?.SafeDispose();
_connectLock.Release();
}
}
@@ -110,6 +114,10 @@ public abstract class TcpServiceChannelBase : TcpService, ITcp
}
finally
{
+ var cts = m_transport;
+ m_transport = null;
+ cts?.SafeCancel();
+ cts?.SafeDispose();
_connectLock.Release();
}
}
@@ -121,6 +129,14 @@ public abstract class TcpServiceChannelBase : TcpService, ITcp
return Result.Success;
}
+ public CancellationToken ClosedToken => this.m_transport == null ? new CancellationToken(true) : this.m_transport.Token;
+ private CancellationTokenSource m_transport;
+
+ protected override void SafetyDispose(bool disposing)
+ {
+ m_transport?.SafeDispose();
+ base.SafetyDispose(disposing);
+ }
///
protected override Task OnTcpClosed(TClient socketClient, ClosedEventArgs e)
{
@@ -208,10 +224,16 @@ public class TcpServiceChannel : TcpServiceChannelBase, IChann
protected override TClient NewClient()
{
var data = new TClient();
- data.WaitHandlePool.MaxSign = MaxSign;
+ data.ResetSign(MinSign, MaxSign);
return data;
}
public int MaxSign { get; set; }
+ public int MinSign { get; set; }
+ public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
+ {
+ MinSign = minSign;
+ MaxSign = maxSign;
+ }
///
protected override async Task OnTcpClosing(TClient socketClient, ClosingEventArgs e)
{
@@ -264,6 +286,7 @@ public class TcpServiceChannel : TcpServiceChannelBase, IChann
IEnumerable ITcpServiceChannel.Clients => base.Clients;
+
protected override void ClientInitialized(TClient client)
{
client.ChannelOptions = ChannelOptions;
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs
index 8c92a29b6..d2ce525be 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/TcpSessionClientChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -22,11 +22,15 @@ public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
///
public TcpSessionClientChannel()
{
- WaitHandlePool.MaxSign = ushort.MaxValue;
}
- public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
-
+ public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
+ {
+ var pool = WaitHandlePool;
+ WaitHandlePool = new WaitHandlePool(minSign, maxSign);
+ pool?.CancelAll();
+ pool?.SafeDispose();
+ }
///
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
@@ -92,10 +96,10 @@ public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
}
///
- protected override void Dispose(bool disposing)
+ protected override void SafetyDispose(bool disposing)
{
WaitHandlePool.SafeDispose();
- base.Dispose(disposing);
+ base.SafetyDispose(disposing);
}
///
diff --git a/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs b/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs
index f0ec95178..ca51dc6a9 100644
--- a/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Channel/UdpSessionChannel.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -25,11 +25,16 @@ public class UdpSessionChannel : UdpSession, IClientChannel
public UdpSessionChannel(IChannelOptions channelOptions)
{
ChannelOptions = channelOptions;
- WaitHandlePool.MaxSign = ushort.MaxValue;
}
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
- public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
+ public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
+ {
+ var pool = WaitHandlePool;
+ WaitHandlePool = new WaitHandlePool(minSign, maxSign);
+ pool?.CancelAll();
+ pool?.SafeDispose();
+ }
///
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
@@ -92,7 +97,8 @@ public class UdpSessionChannel : UdpSession, IClientChannel
if (adapter is UdpDataHandlingAdapter udpDataHandlingAdapter)
SetAdapter(udpDataHandlingAdapter);
}
-
+ public CancellationToken ClosedToken => this.m_transport == null ? new CancellationToken(true) : this.m_transport.Token;
+ private CancellationTokenSource m_transport;
///
public override async Task StartAsync()
{
@@ -120,6 +126,10 @@ public class UdpSessionChannel : UdpSession, IClientChannel
}
finally
{
+ var cts = m_transport;
+ m_transport = new();
+ cts?.SafeCancel();
+ cts?.SafeDispose();
_connectLock.Release();
}
}
@@ -152,6 +162,10 @@ public class UdpSessionChannel : UdpSession, IClientChannel
}
finally
{
+ var cts = m_transport;
+ m_transport = null;
+ cts?.SafeCancel();
+ cts?.SafeDispose();
_connectLock.Release();
}
}
@@ -188,9 +202,10 @@ public class UdpSessionChannel : UdpSession, IClientChannel
}
///
- protected override void Dispose(bool disposing)
+ protected override void SafetyDispose(bool disposing)
{
+ m_transport?.SafeDispose();
WaitHandlePool.SafeDispose();
- base.Dispose(disposing);
+ base.SafetyDispose(disposing);
}
}
diff --git a/src/Foundation/ThingsGateway.Foundation/Converter/EncodingConverter.cs b/src/Foundation/ThingsGateway.Foundation/Converter/EncodingConverter.cs
index 9b49910ef..90b79cf28 100644
--- a/src/Foundation/ThingsGateway.Foundation/Converter/EncodingConverter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Converter/EncodingConverter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Converter/JsonToClassConverter.cs b/src/Foundation/ThingsGateway.Foundation/Converter/JsonToClassConverter.cs
index 4cc9988e6..10cf5ce28 100644
--- a/src/Foundation/ThingsGateway.Foundation/Converter/JsonToClassConverter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Converter/JsonToClassConverter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Converter/StringConverter.cs b/src/Foundation/ThingsGateway.Foundation/Converter/StringConverter.cs
index b1f96bc90..2a92fe81f 100644
--- a/src/Foundation/ThingsGateway.Foundation/Converter/StringConverter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Converter/StringConverter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Converter/ThingsGatewayStringConverter.cs b/src/Foundation/ThingsGateway.Foundation/Converter/ThingsGatewayStringConverter.cs
index 2aacababd..f03140055 100644
--- a/src/Foundation/ThingsGateway.Foundation/Converter/ThingsGatewayStringConverter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Converter/ThingsGatewayStringConverter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceSingleStreamDataHandleAdapter.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceSingleStreamDataHandleAdapter.cs
index 8fa5ce96b..99d705ff7 100644
--- a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceSingleStreamDataHandleAdapter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceSingleStreamDataHandleAdapter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -27,9 +27,6 @@ public class DeviceSingleStreamDataHandleAdapter : TcpCustomDataHandli
///
public override bool CanSendRequestInfo => true;
- ///
- public override bool CanSplicingSend => false;
-
///
/// 报文输出时采用字符串还是HexString
///
@@ -171,23 +168,24 @@ public class DeviceSingleStreamDataHandleAdapter : TcpCustomDataHandli
}
///
- protected override async Task PreviewSendAsync(ReadOnlyMemory memory)
+ protected override async Task PreviewSendAsync(ReadOnlyMemory memory, CancellationToken cancellationToken)
{
+ cancellationToken.ThrowIfCancellationRequested();
if (Logger?.LogLevel <= LogLevel.Trace)
Logger?.Trace($"{ToString()}- Send:{(IsHexLog ? memory.Span.ToHexString() : (memory.Span.ToString(Encoding.UTF8)))}");
//发送
- await GoSendAsync(memory).ConfigureAwait(false);
+ await GoSendAsync(memory, cancellationToken).ConfigureAwait(false);
}
///
- protected override async Task PreviewSendAsync(IRequestInfo requestInfo)
+ protected override async Task PreviewSendAsync(IRequestInfo requestInfo, CancellationToken cancellationToken)
{
if (!(requestInfo is ISendMessage sendMessage))
{
throw new Exception($"Unable to convert {nameof(requestInfo)} to {nameof(ISendMessage)}");
}
-
+ cancellationToken.ThrowIfCancellationRequested();
var byteBlock = new ValueByteBlock(sendMessage.MaxLength);
try
{
@@ -199,7 +197,7 @@ public class DeviceSingleStreamDataHandleAdapter : TcpCustomDataHandli
{
SetRequest(sendMessage, ref byteBlock);
}
- await GoSendAsync(byteBlock.Memory).ConfigureAwait(false);
+ await GoSendAsync(byteBlock.Memory, cancellationToken).ConfigureAwait(false);
}
finally
{
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceUdpDataHandleAdapter.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceUdpDataHandleAdapter.cs
index 55a525967..3687d9fd4 100644
--- a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceUdpDataHandleAdapter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/DeviceUdpDataHandleAdapter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -21,9 +21,6 @@ public class DeviceUdpDataHandleAdapter : UdpDataHandlingAdapter where
///
public override bool CanSendRequestInfo => true;
- ///
- public override bool CanSplicingSend => false;
-
///
/// 报文输出时采用字符串还是HexString
///
@@ -61,7 +58,7 @@ public class DeviceUdpDataHandleAdapter : UdpDataHandlingAdapter where
}
///
- protected override async Task PreviewReceived(EndPoint remoteEndPoint, ByteBlock byteBlock)
+ protected override async Task PreviewReceived(EndPoint remoteEndPoint, IByteBlockReader byteBlock)
{
try
{
@@ -149,23 +146,24 @@ public class DeviceUdpDataHandleAdapter : UdpDataHandlingAdapter where
}
///
- protected override async Task PreviewSendAsync(EndPoint endPoint, ReadOnlyMemory memory)
+ protected override async Task PreviewSendAsync(EndPoint endPoint, ReadOnlyMemory memory, CancellationToken cancellationToken)
{
+ cancellationToken.ThrowIfCancellationRequested();
+
if (Logger?.LogLevel <= LogLevel.Trace)
Logger?.Trace($"{ToString()}- Send:{(IsHexLog ? memory.Span.ToHexString() : (memory.Span.ToString(Encoding.UTF8)))}");
-
//发送
- await GoSendAsync(endPoint, memory).ConfigureAwait(false);
+ await GoSendAsync(endPoint, memory, cancellationToken).ConfigureAwait(false);
}
///
- protected override async Task PreviewSendAsync(EndPoint endPoint, IRequestInfo requestInfo)
+ protected override async Task PreviewSendAsync(EndPoint endPoint, IRequestInfo requestInfo, CancellationToken cancellationToken)
{
if (!(requestInfo is ISendMessage sendMessage))
{
throw new Exception($"Unable to convert {nameof(requestInfo)} to {nameof(ISendMessage)}");
}
-
+ cancellationToken.ThrowIfCancellationRequested();
var byteBlock = new ValueByteBlock(sendMessage.MaxLength);
try
{
@@ -177,7 +175,7 @@ public class DeviceUdpDataHandleAdapter : UdpDataHandlingAdapter where
{
SetRequest(sendMessage, ref byteBlock);
}
- await GoSendAsync(endPoint, byteBlock.Memory).ConfigureAwait(false);
+ await GoSendAsync(endPoint, byteBlock.Memory, cancellationToken).ConfigureAwait(false);
}
finally
{
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IByteBlockWriterBuilder.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IByteBlockWriterBuilder.cs
new file mode 100644
index 000000000..cd97971a6
--- /dev/null
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IByteBlockWriterBuilder.cs
@@ -0,0 +1,46 @@
+//------------------------------------------------------------------------------
+// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
+// 此代码版权(除特别声明外的代码)归作者本人Diego所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议
+// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
+// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
+// 使用文档:https://thingsgateway.cn/
+// QQ群:605534569
+//------------------------------------------------------------------------------
+
+namespace ThingsGateway.Foundation;
+
+
+///
+/// 定义了字节块构建器的接口,用于从内存池中构建和管理字节块。
+///
+public interface IByteBlockWriterBuilder
+{
+ ///
+ /// 构建数据时,指示内存池的申请长度。
+ ///
+ /// 建议:该值可以尽可能的设置大一些,这样可以避免内存池扩容。
+ ///
+ ///
+ int MaxLength { get; }
+
+ ///
+ /// 构建对象到
+ ///
+ /// 要构建的字节块对象引用。
+ void Build(ref TWriter writer) where TWriter : IByteBlockWriter
+#if AllowsRefStruct
+,allows ref struct
+#endif
+ ;
+}
+
+
+
+///
+/// 指示应当如何构建
+///
+public interface IRequestInfoByteBlockWriterBuilder : IRequestInfo, IByteBlockWriterBuilder
+{
+
+}
\ No newline at end of file
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IResultMessage.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IResultMessage.cs
index f1b0d66a6..8567845bf 100644
--- a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IResultMessage.cs
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/IResultMessage.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -23,7 +23,7 @@ public interface IResultMessage : IOperResult, IRequestInfo
///
/// 解析的字节信息
///
- byte[] Content { get; set; }
+ ReadOnlyMemory Content { get; set; }
///
/// 消息头的指令长度,不固定时返回0
@@ -42,14 +42,14 @@ public interface IResultMessage : IOperResult, IRequestInfo
/// 然后返回
///
/// 是否成功有效
- FilterResult CheckBody(ref TByteBlock byteBlock) where TByteBlock : IByteBlock;
+ FilterResult CheckBody(ref TByteBlock byteBlock) where TByteBlock : IByteBlockReader;
///
/// 检查头子节的合法性,并赋值
/// 如果返回false,意味着放弃本次解析的所有数据,包括已经解析完成的Header
///
/// 是否成功的结果
- bool CheckHead(ref TByteBlock byteBlock) where TByteBlock : IByteBlock;
+ bool CheckHead(ref TByteBlock byteBlock) where TByteBlock : IByteBlockReader;
///
/// 发送前的信息处理,例如存储某些特征信息:站号/功能码等等用于验证后续的返回信息是否合法
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/ISendMessage.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/ISendMessage.cs
index c6d2cc9cd..71c26e8c8 100644
--- a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/ISendMessage.cs
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/ISendMessage.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -13,6 +13,6 @@ namespace ThingsGateway.Foundation;
///
/// 发送消息
///
-public interface ISendMessage : IRequestInfo, IWaitHandle, IRequestInfoBuilder
+public interface ISendMessage : IRequestInfo, IWaitHandle, IRequestInfoByteBlockWriterBuilder
{
}
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/MessageBase.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/MessageBase.cs
index fb8b44642..6797a2e80 100644
--- a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/MessageBase.cs
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/MessageBase.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -11,7 +11,7 @@
namespace ThingsGateway.Foundation;
///
-public class MessageBase : OperResultClass, IResultMessage, IWaitHandle
+public class MessageBase : OperResultClass>, IResultMessage, IWaitHandle
{
#region 构造
@@ -42,13 +42,13 @@ public class MessageBase : OperResultClass, IResultMessage, IWaitHandle
public virtual int Sign { get; set; } = -1;
///
- public virtual FilterResult CheckBody(ref TByteBlock byteBlock) where TByteBlock : IByteBlock
+ public virtual FilterResult CheckBody(ref TByteBlock byteBlock) where TByteBlock : IByteBlockReader
{
return FilterResult.Success;
}
///
- public virtual bool CheckHead(ref TByteBlock byteBlock) where TByteBlock : IByteBlock
+ public virtual bool CheckHead(ref TByteBlock byteBlock) where TByteBlock : IByteBlockReader
{
return true;
}
diff --git a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/TcpCustomDataHandlingAdapter.cs b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/TcpCustomDataHandlingAdapter.cs
index 251cc0978..2fe2edc83 100644
--- a/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/TcpCustomDataHandlingAdapter.cs
+++ b/src/Foundation/ThingsGateway.Foundation/DataHandleAdapter/TcpCustomDataHandlingAdapter.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
// CSDN博客:https://blog.csdn.net/qq_40374647
@@ -13,14 +13,14 @@
namespace ThingsGateway.Foundation;
///
-/// 用户自定义数据处理适配器,使用该适配器时,接收方收到的数据中,将为null,
+/// 用户自定义数据处理适配器,使用该适配器时,接收方收到的数据中,将为,
/// 同时将实现为TRequest,发送数据直接发送。
///
public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataHandlingAdapter where TRequest : IRequestInfo
{
- private ValueByteBlock m_tempByteBlock;
-
private readonly Type m_requestType;
+ private ValueByteBlock m_tempByteBlock;
+ private TRequest m_tempRequest;
///
/// 初始化自定义数据处理适配器。
@@ -33,16 +33,9 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
this.m_requestType = typeof(TRequest);
}
- private TRequest m_tempRequest;
-
///
public override bool CanSendRequestInfo => false;
- ///
- /// 默认不支持拼接发送
- ///
- public override bool CanSplicingSend => false;
-
///
/// 指示需要解析当前包的剩余长度。如果不能得知,请赋值。
///
@@ -52,10 +45,10 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
/// 尝试解析请求数据块。
///
/// 字节块类型,必须实现IByteBlock接口。
- /// 待解析的字节块。
+ /// 待解析的字节块。
/// 解析出的请求对象。
/// 解析是否成功。
- public bool TryParseRequest(ref TByteBlock byteBlock, out TRequest request) where TByteBlock : IByteBlock
+ public bool TryParseRequest(ref TByteBlock reader, out TRequest request) where TByteBlock : IByteBlockReader
{
// 检查缓存是否超时,如果超时则清除缓存。
if (this.CacheTimeoutEnable && DateTimeOffset.UtcNow - this.LastCacheTime > this.CacheTimeout)
@@ -66,7 +59,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
// 如果临时字节块为空,则尝试直接解析。
if (this.m_tempByteBlock.IsEmpty)
{
- return this.Single(ref byteBlock, out request) == FilterResult.Success;
+ return this.Single(ref reader, out request) == FilterResult.Success;
}
else
{
@@ -77,16 +70,16 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
}
// 计算本次可以读取的长度。
- var len = Math.Min(this.SurLength, byteBlock.CanReadLength);
+ var len = Math.Min(this.SurLength, reader.CanReadLength);
// 从输入字节块中读取数据到临时字节块中。
var block = this.m_tempByteBlock;
- block.Write(byteBlock.Span.Slice(byteBlock.Position, len));
- byteBlock.Position += len;
+ block.Write(reader.Span.Slice(reader.Position, len));
+ reader.Position += len;
this.SurLength -= len;
// 重置临时字节块并准备下一次使用。
- this.m_tempByteBlock = ValueByteBlock.Empty;
+ this.m_tempByteBlock = default;
// 回到字节块的起始位置。
block.SeekToStart();
@@ -101,7 +94,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
// 如果临时字节块不为空,则继续缓存。
if (!this.m_tempByteBlock.IsEmpty)
{
- byteBlock.Position += this.m_tempByteBlock.Length;
+ reader.Position += this.m_tempByteBlock.Length;
}
return false;
}
@@ -110,7 +103,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
// 如果字节块中还有剩余数据,则回退指针。
if (block.CanReadLength > 0)
{
- byteBlock.Position -= block.CanReadLength;
+ reader.Position -= block.CanReadLength;
}
return true;
}
@@ -119,7 +112,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
// 对于需要继续解析的情况,也回退指针。
if (block.CanReadLength > 0)
{
- byteBlock.Position -= block.CanReadLength;
+ reader.Position -= block.CanReadLength;
}
return false;
}
@@ -138,13 +131,23 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
/// 当数据部分异常时,请移动到指定位置,然后返回
/// 当完全满足解析条件时,请返回最后将移至指定位置。
///
- /// 字节块
+ /// 字节块
/// 是否为上次遗留对象,当该参数为时,request也将是上次实例化的对象。
/// 对象。
/// 缓存容量。当需要首次缓存时,指示申请的ByteBlock的容量。合理的值可避免ByteBlock扩容带来的性能消耗。
///
- protected abstract FilterResult Filter(ref TByteBlock byteBlock, bool beCached, ref TRequest request, ref int tempCapacity)
- where TByteBlock : IByteBlock;
+ protected abstract FilterResult Filter(ref TByteBlock reader, bool beCached, ref TRequest request, ref int tempCapacity)
+ where TByteBlock : IByteBlockReader;
+
+ ///
+ /// 判断请求对象是否应该被缓存。
+ ///
+ /// 请求对象。
+ /// 返回布尔值,指示请求对象是否应该被缓存。
+ protected virtual bool IsBeCached(in TRequest request)
+ {
+ return this.m_requestType.IsValueType ? request.GetHashCode() != default(TRequest).GetHashCode() : request != null;
+ }
///
/// 成功执行接收以后。
@@ -155,7 +158,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
}
///
- /// 即将执行。
+ /// 即将执行。
///
///
/// 返回值标识是否继续执行
@@ -166,7 +169,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
///
///
- protected override async Task PreviewReceivedAsync(ByteBlock byteBlock)
+ protected override async Task PreviewReceivedAsync(IByteBlockReader byteBlock)
{
if (this.CacheTimeoutEnable && DateTimeOffset.UtcNow - this.LastCacheTime > this.CacheTimeout)
{
@@ -174,14 +177,16 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
}
if (this.m_tempByteBlock.IsEmpty)
{
- await this.SingleAsync(byteBlock, false).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ await this.SingleAsync(byteBlock).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
}
else
{
this.m_tempByteBlock.Write(byteBlock.Span);
- var block = this.m_tempByteBlock;
- this.m_tempByteBlock = ValueByteBlock.Empty;
- await this.SingleAsync(block, true).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ using (var block = this.m_tempByteBlock)
+ {
+ this.m_tempByteBlock = default;
+ await this.SingleAsync(block).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
+ }
}
}
@@ -189,37 +194,25 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
protected override void Reset()
{
this.m_tempByteBlock.SafeDispose();
- this.m_tempByteBlock = ValueByteBlock.Empty;
+ this.m_tempByteBlock = default;
this.m_tempRequest = default;
this.SurLength = 0;
base.Reset();
}
- ///
- /// 判断请求对象是否应该被缓存。
- ///
- /// 请求对象。
- /// 返回布尔值,指示请求对象是否应该被缓存。
- protected virtual bool IsBeCached(in TRequest request)
- {
- // 如果请求对象类型是值类型,则判断其哈希码是否与默认值不同;
- // 如果是引用类型,则判断对象本身是否为null。
- return this.m_requestType.IsValueType ? request.GetHashCode() != default(TRequest).GetHashCode() : request != null;
- }
-
///
/// 处理单个字节块,提取请求对象。
///
/// 字节块类型,需要实现IByteBlock接口。
- /// 字节块,将被解析以提取请求对象。
+ /// 字节块,将被解析以提取请求对象。
/// 输出参数,提取出的请求对象。
/// 返回过滤结果,指示处理的状态。
- protected FilterResult Single(ref TByteBlock byteBlock, out TRequest request) where TByteBlock : IByteBlock
+ protected FilterResult Single(ref TByteBlock reader, out TRequest request) where TByteBlock : IByteBlockReader
{
// 初始化临时缓存容量。
var tempCapacity = 1024 * 64;
// 执行过滤操作,根据是否应该缓存来决定如何处理字节块和请求对象。
- var filterResult = this.Filter(ref byteBlock, this.IsBeCached(this.m_tempRequest), ref this.m_tempRequest, ref tempCapacity);
+ var filterResult = this.Filter(ref reader, this.IsBeCached(this.m_tempRequest), ref this.m_tempRequest, ref tempCapacity);
switch (filterResult)
{
case FilterResult.Success:
@@ -230,10 +223,10 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
case FilterResult.Cache:
// 如果过滤结果需要缓存,则创建一个新的字节块来缓存数据。
- if (byteBlock.CanReadLength > 0)
+ if (reader.CanReadLength > 0)
{
this.m_tempByteBlock = new ValueByteBlock(tempCapacity);
- this.m_tempByteBlock.Write(byteBlock.Span.Slice(byteBlock.Position, byteBlock.CanReadLength));
+ this.m_tempByteBlock.Write(reader.Span.Slice(reader.Position, reader.CanReadLength));
// 如果缓存的数据长度超过设定的最大包大小,则抛出异常。
if (this.m_tempByteBlock.Length > this.MaxPackageSize)
@@ -242,7 +235,7 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
}
// 将字节块指针移到末尾。
- byteBlock.SeekToEnd();
+ reader.Advance((int)reader.BytesRemaining);
}
// 更新缓存时间。
if (this.UpdateCacheTimeWhenRev)
@@ -264,17 +257,17 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
}
}
- private async Task SingleAsync(TByteBlock byteBlock, bool temp) where TByteBlock : IByteBlock
+ private async Task SingleAsync(TByteBlock reader) where TByteBlock : IByteBlockReader
{
- byteBlock.Position = 0;
- while (byteBlock.Position < byteBlock.Length)
+ reader.Position = 0;
+ while (reader.Position < reader.Length)
{
if (this.DisposedValue)
{
return;
}
var tempCapacity = 1024 * 64;
- var filterResult = this.Filter(ref byteBlock, this.IsBeCached(this.m_tempRequest), ref this.m_tempRequest, ref tempCapacity);
+ var filterResult = this.Filter(ref reader, this.IsBeCached(this.m_tempRequest), ref this.m_tempRequest, ref tempCapacity);
switch (filterResult)
{
@@ -288,26 +281,12 @@ public abstract class TcpCustomDataHandlingAdapter : SingleStreamDataH
break;
case FilterResult.Cache:
- //if (byteBlock.CanReadLength > 0)
- {
- if (temp)
- {
- this.m_tempByteBlock = new ValueByteBlock(tempCapacity);
- this.m_tempByteBlock.Write(byteBlock.Span);
- //this.m_tempByteBlock.Write(byteBlock.Span.Slice(byteBlock.Position, byteBlock.CanReadLength));
- byteBlock.Dispose();
- }
- else
- {
- this.m_tempByteBlock = new ValueByteBlock(tempCapacity);
- this.m_tempByteBlock.Write(byteBlock.Span);
- //this.m_tempByteBlock.Write(byteBlock.Span.Slice(byteBlock.Position, byteBlock.CanReadLength));
- }
+ this.m_tempByteBlock = new ValueByteBlock(tempCapacity);
+ this.m_tempByteBlock.Write(reader.Span);
- if (this.m_tempByteBlock.Length > this.MaxPackageSize)
- {
- this.OnError(default, $"The parsed signal was not received when the cached data length {m_tempByteBlock.Length} exceeds the set value {MaxPackageSize}", true, true);
- }
+ if (this.m_tempByteBlock.Length > this.MaxPackageSize)
+ {
+ this.OnError(default, $"The parsed signal was not received when the cached data length {m_tempByteBlock.Length} exceeds the set value {MaxPackageSize}", true, true);
}
if (this.UpdateCacheTimeWhenRev)
{
diff --git a/src/Foundation/ThingsGateway.Foundation/Device/DeviceBase.cs b/src/Foundation/ThingsGateway.Foundation/Device/DeviceBase.cs
index 6577b8e59..5ab26681e 100644
--- a/src/Foundation/ThingsGateway.Foundation/Device/DeviceBase.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Device/DeviceBase.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -17,6 +17,8 @@ using ThingsGateway.Foundation.Extension.String;
using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
+using TouchSocket.SerialPorts;
+
namespace ThingsGateway.Foundation;
///
@@ -70,13 +72,17 @@ public abstract class DeviceBase : DisposableObject, IDevice
}
else
{
+ channel.Config.SetSerialDataHandlingAdapter(() =>
+ {
+ var adapter = GetDataAdapter() as SingleStreamDataHandlingAdapter;
+ return adapter;
+ });
channel.Config.SetTcpDataHandlingAdapter(() =>
{
var adapter = GetDataAdapter() as SingleStreamDataHandlingAdapter;
return adapter;
});
}
- clientChannel.SetDataHandlingAdapter(GetDataAdapter());
}
else if (Channel is ITcpServiceChannel serviceChannel)
{
@@ -345,11 +351,11 @@ public abstract class DeviceBase : DisposableObject, IDevice
if (channel is IDtuUdpSessionChannel udpSession)
{
- await udpSession.SendAsync(endPoint, sendMessage).ConfigureAwait(false);
+ await udpSession.SendAsync(endPoint, sendMessage, token).ConfigureAwait(false);
}
else
{
- await channel.SendAsync(sendMessage).ConfigureAwait(false);
+ await channel.SendAsync(sendMessage, token).ConfigureAwait(false);
}
return OperResult.Success;
@@ -487,28 +493,22 @@ public abstract class DeviceBase : DisposableObject, IDevice
}
///
- public virtual ValueTask> SendThenReturnAsync(ISendMessage sendMessage, CancellationToken cancellationToken = default)
+ public virtual ValueTask>> SendThenReturnAsync(ISendMessage sendMessage, CancellationToken cancellationToken = default)
{
var channelResult = GetChannel(this is IDtu dtu ? dtu.DtuId : null);
- if (!channelResult.IsSuccess) return EasyValueTask.FromResult(new OperResult(channelResult));
+ if (!channelResult.IsSuccess) return EasyValueTask.FromResult(new OperResult>(channelResult));
return SendThenReturnAsync(sendMessage, channelResult.Content, cancellationToken);
}
- ///
- protected virtual async ValueTask SendThenReturnMessageAsync(ISendMessage sendMessage, CancellationToken cancellationToken = default)
- {
- var channelResult = GetChannel(this is IDtu dtu ? dtu.DtuId : null);
- if (!channelResult.IsSuccess) return new MessageBase(channelResult);
- return await SendThenReturnMessageBaseAsync(sendMessage, channelResult.Content, cancellationToken).ConfigureAwait(false);
- }
+
///
- public virtual async ValueTask> SendThenReturnAsync(ISendMessage sendMessage, IClientChannel channel, CancellationToken cancellationToken = default)
+ public virtual async ValueTask>> SendThenReturnAsync(ISendMessage sendMessage, IClientChannel channel, CancellationToken cancellationToken = default)
{
try
{
- var result = await SendThenReturnMessageBaseAsync(sendMessage, channel, cancellationToken).ConfigureAwait(false);
- return new OperResult(result) { Content = result.Content };
+ var result = await SendThenReturnMessageAsync(sendMessage, channel, cancellationToken).ConfigureAwait(false);
+ return new OperResult>(result) { Content = result.Content };
}
catch (Exception ex)
{
@@ -517,7 +517,15 @@ public abstract class DeviceBase : DisposableObject, IDevice
}
///
- protected virtual ValueTask SendThenReturnMessageBaseAsync(ISendMessage command, IClientChannel clientChannel = default, CancellationToken cancellationToken = default)
+ protected virtual async ValueTask SendThenReturnMessageAsync(ISendMessage sendMessage, CancellationToken cancellationToken = default)
+ {
+ var channelResult = GetChannel(this is IDtu dtu ? dtu.DtuId : null);
+ if (!channelResult.IsSuccess) return new MessageBase(channelResult);
+ return await SendThenReturnMessageAsync(sendMessage, channelResult.Content, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ protected virtual ValueTask SendThenReturnMessageAsync(ISendMessage command, IClientChannel clientChannel, CancellationToken cancellationToken = default)
{
return GetResponsedDataAsync(command, clientChannel, Timeout, cancellationToken);
}
@@ -612,13 +620,13 @@ public abstract class DeviceBase : DisposableObject, IDevice
#region 动态类型读写
///
- public virtual async ValueTask> ReadAsync(string address, int length, DataTypeEnum dataType, CancellationToken cancellationToken = default)
+ public virtual async ValueTask> ReadArrayAsync(string address, int length, DataTypeEnum dataType, CancellationToken cancellationToken = default)
{
return dataType switch
{
DataTypeEnum.String => await ReadStringAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
DataTypeEnum.Boolean => await ReadBooleanAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Byte => await ReadAsync(address, length, cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Byte => (await ReadAsync(address, length, cancellationToken).ConfigureAwait(false)).OperResultFrom(a => a.ToArray()),
DataTypeEnum.Int16 => await ReadInt16Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
DataTypeEnum.UInt16 => await ReadUInt16Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
DataTypeEnum.Int32 => await ReadInt32Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
@@ -627,12 +635,13 @@ public abstract class DeviceBase : DisposableObject, IDevice
DataTypeEnum.UInt64 => await ReadUInt64Async(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
DataTypeEnum.Single => await ReadSingleAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
DataTypeEnum.Double => await ReadDoubleAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Decimal => await ReadDecimalAsync(address, length, cancellationToken: cancellationToken).ConfigureAwait(false),
_ => new OperResult(string.Format(AppResource.DataTypeNotSupported, dataType)),
};
}
///
- public virtual async ValueTask WriteAsync(string address, JToken value, DataTypeEnum dataType, CancellationToken cancellationToken = default)
+ public virtual async ValueTask WriteJTokenAsync(string address, JToken value, DataTypeEnum dataType, CancellationToken cancellationToken = default)
{
try
{
@@ -641,17 +650,18 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
return dataType switch
{
- DataTypeEnum.String => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Boolean => await WriteAsync(address, jArray.ToObject(), cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Byte => await WriteAsync(address, jArray.ToObject(), dataType, cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Int16 => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.UInt16 => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Int32 => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.UInt32 => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Int64 => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.UInt64 => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Single => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
- DataTypeEnum.Double => await WriteAsync(address, jArray.ToObject(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.String => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Boolean => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Byte => await WriteAsync(address, jArray.ToObject().AsMemory(), dataType, cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Int16 => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.UInt16 => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Int32 => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.UInt32 => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Int64 => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.UInt64 => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Single => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Double => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Decimal => await WriteAsync(address, jArray.ToObject().AsMemory(), cancellationToken: cancellationToken).ConfigureAwait(false),
_ => new OperResult(string.Format(AppResource.DataTypeNotSupported, dataType)),
};
}
@@ -670,6 +680,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
DataTypeEnum.UInt64 => await WriteAsync(address, value.ToObject(), bitConverter, cancellationToken).ConfigureAwait(false),
DataTypeEnum.Single => await WriteAsync(address, value.ToObject(), bitConverter, cancellationToken).ConfigureAwait(false),
DataTypeEnum.Double => await WriteAsync(address, value.ToObject(), bitConverter, cancellationToken).ConfigureAwait(false),
+ DataTypeEnum.Decimal => await WriteAsync(address, value.ToObject(), bitConverter, cancellationToken).ConfigureAwait(false),
_ => new OperResult(string.Format(AppResource.DataTypeNotSupported, dataType)),
};
}
@@ -685,16 +696,16 @@ public abstract class DeviceBase : DisposableObject, IDevice
#region 读取
///
- public abstract ValueTask> ReadAsync(string address, int length, CancellationToken cancellationToken = default);
+ public abstract ValueTask>> ReadAsync(string address, int length, CancellationToken cancellationToken = default);
///
- public virtual async ValueTask> ReadBooleanAsync(string address, int length, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual async ValueTask> ReadBooleanAsync(string address, int length, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, RegisterByteLength, true), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToBoolean(result.Content, GetBitOffsetDefault(address), length, BitReverse(address)));
+ return result.OperResultFrom(() => bitConverter.ToBoolean(result.Content.Span, GetBitOffsetDefault(address), length, BitReverse(address)));
}
///
@@ -702,7 +713,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 2), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToInt16(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToInt16(result.Content.Span, 0, length));
}
///
@@ -710,7 +721,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 2), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToUInt16(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToUInt16(result.Content.Span, 0, length));
}
///
@@ -718,7 +729,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 4), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToInt32(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToInt32(result.Content.Span, 0, length));
}
///
@@ -726,7 +737,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 4), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToUInt32(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToUInt32(result.Content.Span, 0, length));
}
///
@@ -734,7 +745,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 8), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToInt64(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToInt64(result.Content.Span, 0, length));
}
///
@@ -742,7 +753,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 8), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToUInt64(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToUInt64(result.Content.Span, 0, length));
}
///
@@ -750,7 +761,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 4), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToSingle(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToSingle(result.Content.Span, 0, length));
}
///
@@ -758,9 +769,15 @@ public abstract class DeviceBase : DisposableObject, IDevice
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
var result = await ReadAsync(address, GetLength(address, length, 8), cancellationToken).ConfigureAwait(false);
- return result.OperResultFrom(() => bitConverter.ToDouble(result.Content, 0, length));
+ return result.OperResultFrom(() => bitConverter.ToDouble(result.Content.Span, 0, length));
+ }
+ ///
+ public virtual async ValueTask> ReadDecimalAsync(string address, int length, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ {
+ bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
+ var result = await ReadAsync(address, GetLength(address, length, 8), cancellationToken).ConfigureAwait(false);
+ return result.OperResultFrom(() => bitConverter.ToDecimal(result.Content.Span, 0, length));
}
-
///
public virtual async ValueTask> ReadStringAsync(string address, int length, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
@@ -771,13 +788,13 @@ public abstract class DeviceBase : DisposableObject, IDevice
var result = await ReadAsync(address, GetLength(address, len.Value, 1), cancellationToken).ConfigureAwait(false);
return result.OperResultFrom(() =>
{
- List strings = new();
+ String[] strings = new String[length];
for (int i = 0; i < length; i++)
{
- var data = bitConverter.ToString(result.Content, i * bitConverter.StringLength.Value, bitConverter.StringLength.Value);
- strings.Add(data);
+ var data = bitConverter.ToString(result.Content.Span, i * bitConverter.StringLength.Value, bitConverter.StringLength.Value);
+ strings[i] = data;
}
- return strings.ToArray();
+ return strings;
}
);
}
@@ -787,10 +804,10 @@ public abstract class DeviceBase : DisposableObject, IDevice
#region 写入
///
- public abstract ValueTask WriteAsync(string address, byte[] value, DataTypeEnum dataType, CancellationToken cancellationToken = default);
+ public abstract ValueTask WriteAsync(string address, ReadOnlyMemory value, DataTypeEnum dataType, CancellationToken cancellationToken = default);
///
- public abstract ValueTask WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default);
+ public abstract ValueTask WriteAsync(string address, ReadOnlyMemory value, CancellationToken cancellationToken = default);
///
public virtual ValueTask WriteAsync(string address, bool value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
@@ -802,7 +819,7 @@ public abstract class DeviceBase : DisposableObject, IDevice
public virtual ValueTask WriteAsync(string address, byte value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, new byte[] { value }, DataTypeEnum.Byte, cancellationToken);
+ return WriteAsync(address, new byte[] { value }.AsMemory(), DataTypeEnum.Byte, cancellationToken);
}
///
@@ -860,7 +877,12 @@ public abstract class DeviceBase : DisposableObject, IDevice
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Double, cancellationToken);
}
-
+ ///
+ public virtual ValueTask WriteAsync(string address, decimal value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ {
+ bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
+ return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Decimal, cancellationToken);
+ }
///
public virtual ValueTask WriteAsync(string address, string value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
@@ -874,73 +896,81 @@ public abstract class DeviceBase : DisposableObject, IDevice
#region 写入数组
///
- public virtual ValueTask WriteAsync(string address, short[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Int16, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Int16, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, ushort[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.UInt16, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.UInt16, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, int[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Int32, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Int32, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, uint[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.UInt32, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.UInt32, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, long[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Int64, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Int64, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, ulong[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.UInt64, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.UInt64, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, float[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Single, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Single, cancellationToken);
}
///
- public virtual ValueTask WriteAsync(string address, double[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
- return WriteAsync(address, bitConverter.GetBytes(value), DataTypeEnum.Double, cancellationToken);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Double, cancellationToken);
}
///
- public virtual async ValueTask WriteAsync(string address, string[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ public virtual ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
+ {
+ bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
+ return WriteAsync(address, bitConverter.GetBytes(value.Span), DataTypeEnum.Decimal, cancellationToken);
+ }
+
+ ///
+ public virtual async ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default)
{
bitConverter ??= ThingsGatewayBitConverter.GetTransByAddress(address);
if (bitConverter.StringLength == null) return new OperResult(AppResource.StringAddressError);
- List bytes = new();
- foreach (var a in value)
+ List> bytes = new();
+ foreach (var a in value.Span)
{
var data = bitConverter.GetBytes(a);
- bytes.AddRange(data.ArrayExpandToLength(bitConverter.StringLength ?? data.Length));
+ bytes.Add(data.ArrayExpandToLength(bitConverter.StringLength ?? data.Length));
}
- return await WriteAsync(address, bytes.ToArray(), DataTypeEnum.String, cancellationToken).ConfigureAwait(false);
+
+ return await WriteAsync(address, bytes.CombineMemoryBlocks(), DataTypeEnum.String, cancellationToken).ConfigureAwait(false);
}
#endregion 写入数组
@@ -1015,5 +1045,5 @@ public abstract class DeviceBase : DisposableObject, IDevice
}
return a => { };
}
- public abstract ValueTask> ReadAsync(object state, CancellationToken cancellationToken = default);
+ public abstract ValueTask>> ReadAsync(object state, CancellationToken cancellationToken = default);
}
diff --git a/src/Foundation/ThingsGateway.Foundation/Device/DeviceExtension.cs b/src/Foundation/ThingsGateway.Foundation/Device/DeviceExtension.cs
index f64c78c22..8cd9c664d 100644
--- a/src/Foundation/ThingsGateway.Foundation/Device/DeviceExtension.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Device/DeviceExtension.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -99,7 +99,7 @@ public static partial class DeviceExtension
/// 返回的字节数组
/// 任意一个失败时抛出异常
/// 解析结果
- public static OperResult PraseStructContent(this IEnumerable variables, IDevice device, byte[] buffer, bool exWhenAny) where T : IVariable
+ public static OperResult PraseStructContent(this IEnumerable variables, IDevice device, ReadOnlySpan buffer, bool exWhenAny) where T : IVariable
{
var time = DateTime.Now;
var result = OperResult.Success;
diff --git a/src/Foundation/ThingsGateway.Foundation/Device/DtuServiceDeviceBase.cs b/src/Foundation/ThingsGateway.Foundation/Device/DtuServiceDeviceBase.cs
index 4a8f4fdcc..3f4fbe1b5 100644
--- a/src/Foundation/ThingsGateway.Foundation/Device/DtuServiceDeviceBase.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Device/DtuServiceDeviceBase.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
diff --git a/src/Foundation/ThingsGateway.Foundation/Device/IDevice.cs b/src/Foundation/ThingsGateway.Foundation/Device/IDevice.cs
index bccf55242..001d2de50 100644
--- a/src/Foundation/ThingsGateway.Foundation/Device/IDevice.cs
+++ b/src/Foundation/ThingsGateway.Foundation/Device/IDevice.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -121,7 +121,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 数据类型
/// 取消令箭
///
- ValueTask> ReadAsync(string address, int length, DataTypeEnum dataType, CancellationToken cancellationToken = default);
+ ValueTask> ReadArrayAsync(string address, int length, DataTypeEnum dataType, CancellationToken cancellationToken = default);
///
/// 根据数据类型,写入类型值
@@ -131,7 +131,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 数据类型
/// 取消令箭
///
- ValueTask WriteAsync(string address, JToken value, DataTypeEnum dataType, CancellationToken cancellationToken = default);
+ ValueTask WriteJTokenAsync(string address, JToken value, DataTypeEnum dataType, CancellationToken cancellationToken = default);
#endregion 动态类型读写
@@ -144,7 +144,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 读取寄存器数量,对于不同PLC,对应的字节数量可能不一样
/// 取消令箭
///
- ValueTask> ReadAsync(string address, int length, CancellationToken cancellationToken = default);
+ ValueTask>> ReadAsync(string address, int length, CancellationToken cancellationToken = default);
///
/// 读取布尔量数组
@@ -253,12 +253,12 @@ public interface IDevice : IDisposable, IDisposableObject
///
/// 写入原始的byte数组数据到指定的地址,返回结果
///
- ValueTask WriteAsync(string address, byte[] value, DataTypeEnum dataType, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, DataTypeEnum dataType, CancellationToken cancellationToken = default);
///
/// 写入bool数组数据,返回结果
///
- ValueTask WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, CancellationToken cancellationToken = default);
///
/// 写入bool数据,返回结果
@@ -327,7 +327,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 转换规则
/// 取消令箭
/// 写入结果
- ValueTask WriteAsync(string address, string[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
///
/// 写入Double数组
@@ -337,7 +337,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 转换规则
/// 取消令箭
/// 写入结果
- ValueTask WriteAsync(string address, double[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
///
/// 写入Single数组
@@ -347,7 +347,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 转换规则
/// 取消令箭
/// 写入结果
- ValueTask WriteAsync(string address, float[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
///
/// 写入Int32数组
@@ -357,7 +357,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 转换规则
/// 取消令箭
/// 写入结果
- ValueTask WriteAsync(string address, int[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
///
/// 写入Int64数组
@@ -367,7 +367,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 转换规则
/// 取消令箭
/// 写入结果
- ValueTask WriteAsync(string address, long[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
///
/// 写入Int16数组
@@ -377,7 +377,7 @@ public interface IDevice : IDisposable, IDisposableObject
/// 转换规则
/// 取消令箭
/// 写入结果
- ValueTask WriteAsync(string address, short[] value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
+ ValueTask WriteAsync(string address, ReadOnlyMemory value, IThingsGatewayBitConverter bitConverter = null, CancellationToken cancellationToken = default);
///