优化opcua质量戳提示;添加数据转换基础方法;TCP等待返回时默认断开连接立即返回

This commit is contained in:
2248356998 qq.com
2023-05-21 10:51:56 +08:00
parent bd90e8efb2
commit cc79de1106
7 changed files with 294 additions and 51 deletions

View File

@@ -2,8 +2,6 @@ using Mapster;
using Microsoft.Extensions.DependencyInjection;
using NewLife.Reflection;
using Opc.Ua;
using Opc.Ua.Server;
@@ -203,10 +201,18 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
if (initialItemValue != null)
{
var code = variable.quality == 192 ? StatusCodes.Good : StatusCodes.Bad;
if (uaTag.Value != initialItemValue)
ChangeNodeData(uaTag.NodeId.ToString(), initialItemValue, variable.changeTime);
if (code == StatusCodes.Good)
{
ChangeNodeData(uaTag, initialItemValue, variable.changeTime);
}
if (uaTag.StatusCode != code)
uaTag.SetStatusCode(SystemContext, code, variable.changeTime);
{
uaTag.StatusCode = code;
}
uaTag.ClearChangeMasks(SystemContext, false);
}
}
@@ -228,28 +234,22 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
}
/// <summary>
/// 在服务器端直接更改对应数据节点的值,并通知客户端
/// 在服务器端直接更改对应数据节点的值
/// </summary>
private void ChangeNodeData(string nodeId, object value, DateTime dateTime)
private void ChangeNodeData(OPCUATag tag, object value, DateTime dateTime)
{
if (_idTags.ContainsKey(nodeId))
object newValue;
try
{
lock (Lock)
{
object newValue;
try
{
newValue=Convert.ChangeType(value, _idTags[nodeId].NETDataType);
}
catch
{
newValue= value;
}
_idTags[nodeId].Value = newValue;
_idTags[nodeId].Timestamp = dateTime;
_idTags[nodeId].ClearChangeMasks(SystemContext, false);
}
newValue = Convert.ChangeType(value, tag.NETDataType);
}
catch
{
newValue = value;
}
tag.Value = newValue;
tag.Timestamp = dateTime;
//_idTags[nodeId].ClearChangeMasks(SystemContext, false);
}
/// <summary>
@@ -302,9 +302,10 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
variable.AccessLevel = level;
variable.UserAccessLevel = level;
variable.Historizing = variableRunTime.HisEnable;
variable.StatusCode = StatusCodes.Good;
variable.Timestamp = DateTime.UtcNow;
variable.Value = Opc.Ua.TypeInfo.GetDefaultValue(variable.DataType, ValueRanks.Scalar, Server.TypeTree);
var code = variableRunTime.Quality == 192 ? StatusCodes.Good : StatusCodes.Bad;
variable.StatusCode = code;
variable.Timestamp = variableRunTime.CollectTime;
variable.OnWriteValue = OnWriteDataValue;
if (parent != null)
{

View File

@@ -60,6 +60,22 @@ namespace ThingsGateway.Foundation
/// <param name="value">等待转化的数据</param>
/// <returns>buffer数据</returns>
byte[] GetBytes(short value);
/// <inheritdoc/>
byte[] GetBytes(short[] value);
/// <inheritdoc/>
byte[] GetBytes(ushort[] value);
/// <inheritdoc/>
byte[] GetBytes(int[] value);
/// <inheritdoc/>
byte[] GetBytes(uint[] value);
/// <inheritdoc/>
byte[] GetBytes(long[] value);
/// <inheritdoc/>
byte[] GetBytes(ulong[] value);
/// <inheritdoc/>
byte[] GetBytes(float[] value);
/// <inheritdoc/>
byte[] GetBytes(double[] value);
/// <summary>
/// ushort变量转化缓存数据一个ushort数据可以转为2个字节的Byte数组<br />
@@ -151,6 +167,10 @@ namespace ThingsGateway.Foundation
/// <param name="buffer">等待提取的缓存数据</param>
/// <param name="offset">位的索引注意是从0开始的位索引10则表示 buffer[1] 的第二位。</param>
bool ToBoolean(byte[] buffer, int offset);
/// <inheritdoc/>
bool[] ToBoolean(byte[] buffer, int offset, int len);
/// <inheritdoc/>
byte ToByte(byte[] buffer, int offset);
@@ -164,7 +184,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>double对象</returns>
double ToDouble(byte[] buffer, int offset);
/// <inheritdoc/>
double[] ToDouble(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取short结果需要指定起始的字节索引按照字节为单位一个short占用两个字节<br />
/// </summary>
@@ -172,7 +193,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>short对象</returns>
short ToInt16(byte[] buffer, int offset);
/// <inheritdoc/>
short[] ToInt16(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取int结果需要指定起始的字节索引按照字节为单位一个int占用四个字节<br />
/// </summary>
@@ -180,6 +202,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>int对象</returns>
int ToInt32(byte[] buffer, int offset);
/// <inheritdoc/>
int[] ToInt32(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取long结果需要指定起始的字节索引按照字节为单位一个long占用八个字节<br />
@@ -188,7 +212,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>long对象</returns>
long ToInt64(byte[] buffer, int offset);
/// <inheritdoc/>
long[] ToInt64(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取float结果需要指定起始的字节索引按照字节为单位一个float占用四个字节<b />
/// </summary>
@@ -196,7 +221,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>float对象</returns>
float ToSingle(byte[] buffer, int offset);
/// <inheritdoc/>
float[] ToSingle(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取string结果使用指定的编码将全部的缓存转为字符串<br />
/// </summary>
@@ -220,7 +246,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>ushort对象</returns>
ushort ToUInt16(byte[] buffer, int offset);
/// <inheritdoc/>
ushort[] ToUInt16(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取uint结果需要指定起始的字节索引按照字节为单位一个uint占用四个字节<br />
/// </summary>
@@ -228,7 +255,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>uint对象</returns>
uint ToUInt32(byte[] buffer, int offset);
/// <inheritdoc/>
uint[] ToUInt32(byte[] buffer, int offset, int len);
/// <summary>
/// 从缓存中提取ulong结果需要指定起始的字节索引按照字节为单位一个ulong占用八个字节<b />
/// </summary>
@@ -236,6 +264,8 @@ namespace ThingsGateway.Foundation
/// <param name="offset">索引位置</param>
/// <returns>ulong对象</returns>
ulong ToUInt64(byte[] buffer, int offset);
/// <inheritdoc/>
ulong[] ToUInt64(byte[] buffer, int offset, int len);
#endregion ToValue
}

View File

@@ -1,5 +1,7 @@
using Newtonsoft.Json;
using System.Reflection;
namespace ThingsGateway.Foundation
{
/// <summary>
@@ -84,6 +86,17 @@ namespace ThingsGateway.Foundation
}
return bytes;
}
/// <inheritdoc/>
public byte[] GetBytes(short[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(ushort value)
@@ -95,43 +108,113 @@ namespace ThingsGateway.Foundation
}
return bytes;
}
/// <inheritdoc/>
public byte[] GetBytes(ushort[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(int value)
{
return ByteTransDataFormat4(BitConverter.GetBytes(value));
}
/// <inheritdoc/>
public byte[] GetBytes(int[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(uint value)
{
return ByteTransDataFormat4(BitConverter.GetBytes(value));
}
/// <inheritdoc/>
public byte[] GetBytes(uint[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(long value)
{
return ByteTransDataFormat8(BitConverter.GetBytes(value));
}
/// <inheritdoc/>
public byte[] GetBytes(long[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(ulong value)
{
return ByteTransDataFormat8(BitConverter.GetBytes(value));
}
/// <inheritdoc/>
public byte[] GetBytes(ulong[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(float value)
{
return ByteTransDataFormat4(BitConverter.GetBytes(value));
}
/// <inheritdoc/>
public byte[] GetBytes(float[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(double value)
{
return ByteTransDataFormat8(BitConverter.GetBytes(value));
}
/// <inheritdoc/>
public byte[] GetBytes(double[] value)
{
byte[] numArray = new byte[value.Length * 2];
for (int index = 0; index < value.Length; ++index)
{
byte[] bytes = GetBytes(value[index]);
bytes.CopyTo(numArray, 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public byte[] GetBytes(string value)
{
@@ -412,5 +495,103 @@ namespace ThingsGateway.Foundation
}
return numArray;
}
/// <inheritdoc/>
public bool[] ToBoolean(byte[] buffer, int offset, int len)
{
bool[] flagArray = new bool[len];
for (int index = 0; index < len; ++index)
{
flagArray[index] = buffer.GetBoolByIndex(offset + index);
}
return flagArray;
}
/// <inheritdoc/>
public double[] ToDouble(byte[] buffer, int offset, int len)
{
double[] numArray = new double[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToDouble(buffer, offset + 8 * index);
}
return numArray;
}
/// <inheritdoc/>
public short[] ToInt16(byte[] buffer, int offset, int len)
{
short[] numArray = new short[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToInt16(buffer, offset + 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public int[] ToInt32(byte[] buffer, int offset, int len)
{
int[] numArray = new int[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToInt32(buffer, offset + 4 * index);
}
return numArray;
}
/// <inheritdoc/>
public long[] ToInt64(byte[] buffer, int offset, int len)
{
long[] numArray = new long[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToInt64(buffer, offset + 8 * index);
}
return numArray;
}
/// <inheritdoc/>
public float[] ToSingle(byte[] buffer, int offset, int len)
{
float[] numArray = new float[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToSingle(buffer, offset + 4 * index);
}
return numArray;
}
/// <inheritdoc/>
public ushort[] ToUInt16(byte[] buffer, int offset, int len)
{
ushort[] numArray = new ushort[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToUInt16(buffer, offset + 2 * index);
}
return numArray;
}
/// <inheritdoc/>
public uint[] ToUInt32(byte[] buffer, int offset, int len)
{
uint[] numArray = new uint[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToUInt32(buffer, offset + 4 * index);
}
return numArray;
}
/// <inheritdoc/>
public ulong[] ToUInt64(byte[] buffer, int offset, int len)
{
ulong[] numArray = new ulong[len];
for (int index = 0; index < len; ++index)
{
numArray[index] = ToUInt64(buffer, offset + 8* index);
}
return numArray;
}
}
}

View File

@@ -342,10 +342,9 @@ namespace TouchSocket.Sockets
private void BreakOut(string msg, bool manual)
{
try
{
EasyLock.Lock();
privateEasyLock.Lock();
if (this.CanSend)
{
this.CanSend = false;
@@ -359,7 +358,7 @@ namespace TouchSocket.Sockets
}
finally
{
EasyLock.UnLock();
privateEasyLock.UnLock();
}
}
@@ -396,7 +395,7 @@ namespace TouchSocket.Sockets
{
try
{
EasyLock.Lock();
privateEasyLock.Lock();
if (this.CanSend)
{
@@ -480,7 +479,7 @@ namespace TouchSocket.Sockets
finally
{
EasyLock.UnLock();
privateEasyLock.UnLock();
}
@@ -495,7 +494,7 @@ namespace TouchSocket.Sockets
return this;
}
private EasyLock EasyLock { get; set; } = new();
private EasyLock privateEasyLock { get; set; } = new();
/// <summary>
/// 异步连接服务器
@@ -504,7 +503,7 @@ namespace TouchSocket.Sockets
{
try
{
await EasyLock.LockAsync();
await privateEasyLock.LockAsync();
if (this.CanSend)
{
@@ -614,7 +613,7 @@ namespace TouchSocket.Sockets
}
finally
{
EasyLock.UnLock();
privateEasyLock.UnLock();
}
return this;
}

View File

@@ -14,6 +14,7 @@ namespace ThingsGateway.Foundation
/// <returns></returns>
public static IWaitingClient<TClient> GetTGWaitingClient<TClient>(this TClient client, WaitingOptions waitingOptions) where TClient : IClient, IDefaultSender, ISender
{
waitingOptions.BreakTrigger = true;
TGWaitingClient<TClient> waitingClient = new TGWaitingClient<TClient>(client, waitingOptions);
return waitingClient;
}

View File

@@ -19,13 +19,28 @@ namespace ThingsGateway.Web.Foundation
{
IServiceScopeFactory _scopeFactory;
/// <inheritdoc cref="CollectDbInfoControler"/>
public CollectDbInfoControler(IServiceScopeFactory scopeFactory, IVariableService variableService)
public CollectDbInfoControler(IServiceScopeFactory scopeFactory, IVariableService variableService, ICollectDeviceService collectDeviceService)
{
_scopeFactory = scopeFactory;
_variableService = variableService;
_collectDeviceService = collectDeviceService;
}
IVariableService _variableService { get; set; }
ICollectDeviceService _collectDeviceService { get; set; }
/// <summary>
/// 获取采集设备信息
/// </summary>
/// <returns></returns>
[HttpGet("collectDeviceList")]
[Description("获取采集设备信息")]
public async Task<SqlSugarPagedList<CollectDevice>> GetCollectDeviceList([FromQuery] CollectDevicePageInput input)
{
var data = await _collectDeviceService.PageAsync(input);
return data;
}
/// <summary>
/// 获取变量信息
/// </summary>
@@ -38,8 +53,6 @@ namespace ThingsGateway.Web.Foundation
return data;
}
}
}

View File

@@ -108,7 +108,7 @@ public class CollectVariableRunTime : CollectDeviceVariable
time = dateTime;
}
CollectTime = DateTime.UtcNow;
if (data?.ToString() != _value?.ToString() && LastSetValue?.ToString() != data?.ToString())
if (data?.ToString() != _value?.ToString() && LastSetValue?.ToString() != data?.ToString()||qualityChanged)
{
ChangeTime = DateTime.UtcNow;
if (Quality == 192)
@@ -151,12 +151,30 @@ public class CollectVariableRunTime : CollectDeviceVariable
[System.Text.Json.Serialization.JsonIgnore]
[AdaptIgnore]
public VariableCahngeEventHandler VariableValueChange { get; set; }
private int quality;
private bool qualityChanged;
/// <summary>
/// 质量戳
/// </summary>
[Description("质量戳")]
[OrderTable(Order = 5)]
public int Quality { get; private set; }
public int Quality { get => quality; private set
{
if (quality != value)
{
quality = value;
qualityChanged = true;
}
else
{
qualityChanged = false;
}
}
}
#region LoadSourceRead