This commit is contained in:
Diego
2025-07-08 10:19:01 +08:00
parent 46b16279c7
commit 9b5ee1d7d9
13 changed files with 89 additions and 49 deletions

View File

@@ -32,6 +32,10 @@ public class ConcurrentHashSet<T> : IEnumerable<T> where T : notnull
/// <returns></returns>
public Boolean TryRemove(T item) => _dic.TryRemove(item, out _);
public ICollection<T> Keys => _dic.Keys;
public void Clear() => _dic.Clear();
#region IEnumerable<T>
IEnumerator<T> IEnumerable<T>.GetEnumerator() => _dic.Keys.GetEnumerator();
#endregion

View File

@@ -1,5 +1,7 @@
using System.Collections.Concurrent;
using ThingsGateway.NewLife.Collections;
namespace ThingsGateway.NewLife.DictionaryExtensions;
/// <summary>并发字典扩展</summary>
@@ -129,6 +131,33 @@ public static class DictionaryExtensions
}
}
/// <summary>
/// 批量出队
/// </summary>
public static IEnumerable<TKEY> ToIEnumerableWithDequeue<TKEY>(this ConcurrentHashSet<TKEY> values, int maxCount = 0)
{
if (values.IsEmpty) yield break;
if (maxCount <= 0)
{
maxCount = values.Count;
}
else
{
maxCount = Math.Min(maxCount, values.Count);
}
var keys = values.Keys;
foreach (var key in keys)
{
if (maxCount-- <= 0) break;
if (values.TryRemove(key))
{
yield return key;
}
}
}
/// <summary>
/// 批量出队
/// </summary>

View File

@@ -1,9 +1,9 @@
<Project>
<PropertyGroup>
<PluginVersion>10.9.24</PluginVersion>
<ProPluginVersion>10.9.24</ProPluginVersion>
<DefaultVersion>10.9.24</DefaultVersion>
<PluginVersion>10.9.25</PluginVersion>
<ProPluginVersion>10.9.25</ProPluginVersion>
<DefaultVersion>10.9.25</DefaultVersion>
<AuthenticationVersion>2.9.13</AuthenticationVersion>
<SourceGeneratorVersion>10.9.13</SourceGeneratorVersion>
<NET8Version>8.0.17</NET8Version>

View File

@@ -17,6 +17,7 @@ namespace ThingsGateway.Gateway.Application;
public static partial class GatewayMapper
{
public static partial VariableDataWithValue AdaptVariableDataWithValue(this VariableBasicData src);
public static partial VariableDataWithValue AdaptVariableDataWithValue(this VariableRuntime src);
public static partial AlarmVariable AdaptAlarmVariable(this VariableRuntime src);
public static partial DeviceBasicData AdaptDeviceBasicData(this DeviceRuntime src);
public static partial IEnumerable<DeviceBasicData> AdaptIEnumerableDeviceBasicData(this IEnumerable<DeviceRuntime> src);

View File

@@ -89,7 +89,7 @@ internal sealed class RedundancyTask : IRpcDriver, IAsyncDisposable
if (online)
{
int batchSize = GetBatchSize();
int batchSize = 50;
var deviceRunTimes = GlobalData.ReadOnlyIdDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).Batch(batchSize);

View File

@@ -253,10 +253,10 @@ public partial class ChannelTable : IDisposable
ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, PluginName = SelectModel.PluginName });
break;
case ChannelDevicePluginTypeEnum.Channel:
ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, ChannelId = SelectModel.ChannelRuntime.Id });
ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, ChannelId = SelectModel.ChannelRuntimeId });
break;
case ChannelDevicePluginTypeEnum.Device:
ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType });
ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, DeviceId = SelectModel.DeviceRuntimeId, PluginType = SelectModel.TryGetDeviceRuntime(out var deviceRuntime) ? deviceRuntime?.PluginType : null });
break;
default:
ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() });

View File

@@ -1340,14 +1340,14 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
case ChannelDevicePluginTypeEnum.Channel:
return new ChannelDeviceTreeItem()
{
ChannelRuntime = GlobalData.ReadOnlyIdChannels.TryGetValue(channelDeviceTreeItem.ChannelRuntime?.Id ?? 0, out var channel) ? channel : channelDeviceTreeItem.ChannelRuntime,
ChannelRuntimeId = channelDeviceTreeItem.ChannelRuntimeId,
ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Channel
};
case ChannelDevicePluginTypeEnum.Device:
return new ChannelDeviceTreeItem()
{
DeviceRuntime = GlobalData.ReadOnlyIdDevices.TryGetValue(channelDeviceTreeItem.DeviceRuntime?.Id ?? 0, out var device) ? device : channelDeviceTreeItem.DeviceRuntime,
DeviceRuntimeId = channelDeviceTreeItem.DeviceRuntimeId,
ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Device
};
}
@@ -1500,11 +1500,11 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
switch (x.ChannelDevicePluginType)
{
case ChannelDevicePluginTypeEnum.Device:
return x.DeviceRuntime.Id == y.DeviceRuntime.Id;
return x.DeviceRuntimeId == y.DeviceRuntimeId;
case ChannelDevicePluginTypeEnum.PluginType:
return x.PluginType == y.PluginType;
case ChannelDevicePluginTypeEnum.Channel:
return x.ChannelRuntime.Id == y.ChannelRuntime.Id;
return x.ChannelRuntimeId == y.ChannelRuntimeId;
case ChannelDevicePluginTypeEnum.PluginName:
return x.PluginName == y.PluginName;
default:

View File

@@ -22,8 +22,12 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
public long Id { get; set; }
public ChannelDevicePluginTypeEnum ChannelDevicePluginType { get; set; }
public DeviceRuntime DeviceRuntime { get; set; }
public ChannelRuntime ChannelRuntime { get; set; }
public long DeviceRuntimeId { get; set; }
public long ChannelRuntimeId { get; set; }
public string PluginName { get; set; }
public PluginTypeEnum? PluginType { get; set; }
@@ -37,11 +41,11 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
switch (ChannelDevicePluginType)
{
case ChannelDevicePluginTypeEnum.Device:
return DeviceRuntime == item.DeviceRuntime;
return DeviceRuntimeId == item.DeviceRuntimeId;
case ChannelDevicePluginTypeEnum.PluginType:
return PluginType == item.PluginType;
case ChannelDevicePluginTypeEnum.Channel:
return ChannelRuntime == item.ChannelRuntime;
return ChannelRuntimeId == item.ChannelRuntimeId;
case ChannelDevicePluginTypeEnum.PluginName:
return PluginName == item.PluginName;
default:
@@ -54,21 +58,22 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
public override int GetHashCode()
{
return HashCode.Combine(ChannelDevicePluginType, DeviceRuntime, ChannelRuntime, PluginName, PluginType);
return HashCode.Combine(ChannelDevicePluginType, DeviceRuntimeId, ChannelRuntimeId, PluginName, PluginType);
}
public bool TryGetDeviceRuntime(out DeviceRuntime deviceRuntime)
{
if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Device && DeviceRuntime?.Id > 0)
if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Device && DeviceRuntimeId > 0)
{
deviceRuntime = DeviceRuntime;
return true;
}
else
{
deviceRuntime = null;
return false;
if (GlobalData.ReadOnlyIdDevices.TryGetValue(DeviceRuntimeId, out deviceRuntime))
{
return true;
}
}
deviceRuntime = null;
return false;
}
public bool TryGetPluginName(out string pluginName)
{
if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.PluginName)
@@ -98,16 +103,15 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
}
public bool TryGetChannelRuntime(out ChannelRuntime channelRuntime)
{
if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Channel && ChannelRuntime?.Id > 0)
if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Channel && ChannelRuntimeId > 0)
{
channelRuntime = ChannelRuntime;
return true;
}
else
{
channelRuntime = null;
return false;
if (GlobalData.ReadOnlyIdChannels.TryGetValue(ChannelRuntimeId, out channelRuntime))
{
return true;
}
}
channelRuntime = null;
return false;
}
@@ -115,11 +119,11 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
{
if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Device)
{
return DeviceRuntime?.ToString();
return TryGetDeviceRuntime(out var deviceRuntime) ? deviceRuntime?.ToString() : string.Empty;
}
else if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.Channel)
{
return ChannelRuntime?.ToString();
return TryGetChannelRuntime(out var channelRuntime) ? channelRuntime?.ToString() : string.Empty;
}
else if (ChannelDevicePluginType == ChannelDevicePluginTypeEnum.PluginName)
{
@@ -139,6 +143,6 @@ public class ChannelDeviceTreeItem : IEqualityComparer<ChannelDeviceTreeItem>
public int GetHashCode([DisallowNull] ChannelDeviceTreeItem obj)
{
return HashCode.Combine(obj.ChannelDevicePluginType, obj.DeviceRuntime, obj.ChannelRuntime, obj.PluginName, obj.PluginType);
return HashCode.Combine(obj.ChannelDevicePluginType, obj.DeviceRuntimeId, obj.ChannelRuntimeId, obj.PluginName, obj.PluginType);
}
}

View File

@@ -254,10 +254,10 @@ public partial class DeviceTable : IDisposable
ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, PluginName = SelectModel.PluginName });
break;
case ChannelDevicePluginTypeEnum.Channel:
ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, ChannelId = SelectModel.ChannelRuntime.Id });
ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, ChannelId = SelectModel.ChannelRuntimeId });
break;
case ChannelDevicePluginTypeEnum.Device:
ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType });
ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, DeviceId = SelectModel.DeviceRuntimeId, PluginType = SelectModel.TryGetDeviceRuntime(out var deviceRuntime) ? deviceRuntime?.PluginType : null });
break;
default:
ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder } });

View File

@@ -287,7 +287,7 @@ public partial class VariableRuntimeInfo : IDisposable
{
return Task.FromResult(new VariableRuntime()
{
DeviceId = SelectModel?.DeviceRuntime?.IsCollect == true ? SelectModel?.DeviceRuntime?.Id ?? 0 : 0
DeviceId = SelectModel?.TryGetDeviceRuntime(out var deviceRuntime) == true ? deviceRuntime?.IsCollect == true ? deviceRuntime?.Id ?? 0 : 0 : 0
});
}
@@ -313,10 +313,10 @@ public partial class VariableRuntimeInfo : IDisposable
ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, PluginName = SelectModel.PluginName });
break;
case ChannelDevicePluginTypeEnum.Channel:
ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, ChannelId = SelectModel.ChannelRuntime.Id });
ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, ChannelId = SelectModel.ChannelRuntimeId });
break;
case ChannelDevicePluginTypeEnum.Device:
ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType });
ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder }, DeviceId = SelectModel.DeviceRuntimeId, PluginType = SelectModel.TryGetDeviceRuntime(out var deviceRuntime) ? deviceRuntime?.PluginType : null });
break;
default:
ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() { SortName = _option.SortName, SortOrder = _option.SortOrder } });

View File

@@ -118,7 +118,7 @@ public static class ResourceUtil
{
var channelRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Channel, ChannelRuntime = channelRuntime, Id = channelRuntime.Id };
var channelRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Channel, ChannelRuntimeId = channelRuntime.Id, Id = channelRuntime.Id };
var channelTreeItemItem = channelOldItems.FirstOrDefault(a => a.Value.Equals(channelRuntimeTreeItem));
@@ -142,7 +142,7 @@ public static class ResourceUtil
foreach (var keyValue in channelRuntime.ReadDeviceRuntimes.OrderBy(a => a.Value.DeviceStatus))
{
var deviceRuntime = keyValue.Value;
var deviceRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Device, DeviceRuntime = deviceRuntime, Id = deviceRuntime.Id };
var deviceRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Device, DeviceRuntimeId = deviceRuntime.Id, Id = deviceRuntime.Id };
var deviceTreeItemItem = deviceOldItems.FirstOrDefault(a => a.Value.Equals(deviceRuntimeTreeItem));
@@ -204,7 +204,7 @@ public static class ResourceUtil
foreach (var channelRuntime in dict.Where(a => a.Key.PluginName == pluginName))
{
var channelRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Channel, ChannelRuntime = channelRuntime.Key, Id = channelRuntime.Key.Id };
var channelRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Channel, ChannelRuntimeId = channelRuntime.Key.Id, Id = channelRuntime.Key.Id };
var channelTreeItemItem = channelOldItems.FirstOrDefault(a => a.Value.Equals(channelRuntimeTreeItem));
@@ -226,7 +226,7 @@ public static class ResourceUtil
foreach (var deviceRuntime in channelRuntime.Value.OrderBy(a => a.DeviceStatus))
{
var deviceRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Device, DeviceRuntime = deviceRuntime, Id = deviceRuntime.Id };
var deviceRuntimeTreeItem = new ChannelDeviceTreeItem() { ChannelDevicePluginType = ChannelDevicePluginTypeEnum.Device, DeviceRuntimeId = deviceRuntime.Id, Id = deviceRuntime.Id };

View File

@@ -229,7 +229,7 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
/// 更新变量
/// </summary>
/// <param name="variable"></param>
public void UpVariable(VariableBasicData variable)
public void UpVariable(VariableRuntime variable)
{
if (!NodeIdTags.TryGetValue($"{variable.DeviceName}.{variable.Name}", out var uaTag))
return;

View File

@@ -14,10 +14,9 @@ using Microsoft.Extensions.Logging;
using Opc.Ua;
using Opc.Ua.Configuration;
using System.Collections.Concurrent;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Gateway.Application;
using ThingsGateway.NewLife.Collections;
using ThingsGateway.NewLife.DictionaryExtensions;
using TouchSocket.Core;
@@ -44,7 +43,7 @@ public partial class OpcUaServer : BusinessBase
protected override BusinessPropertyBase _businessPropertyBase => _driverPropertys;
protected IStringLocalizer Localizer { get; private set; }
private ConcurrentDictionary<long, VariableBasicData> CollectVariableRuntimes { get; set; } = new();
private ConcurrentHashSet<long> CollectVariableRuntimes { get; set; } = new();
private static readonly string[] separator = new string[] { ";" };
@@ -182,7 +181,10 @@ public partial class OpcUaServer : BusinessBase
{
if (!cancellationToken.IsCancellationRequested)
{
m_server?.NodeManager?.UpVariable(item);
if (IdVariableRuntimes.TryGetValue(item, out var variableRuntime) && variableRuntime != null)
{
m_server?.NodeManager?.UpVariable(variableRuntime);
}
}
else
{
@@ -400,7 +402,7 @@ public partial class OpcUaServer : BusinessBase
if (TaskSchedulerLoop?.Stoped == true) return;
if (DisposedValue) return;
if (IdVariableRuntimes.ContainsKey(variableData.Id))
CollectVariableRuntimes.AddOrUpdate(variableData.Id, id => variableData, (id, addValue) => variableData);
CollectVariableRuntimes.TryAdd(variableData.Id);
else
{