mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-22 11:33:07 +08:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b790cf5f4e | ||
![]() |
d1248811fd | ||
![]() |
022d016e8e | ||
![]() |
f73245e650 | ||
![]() |
484461fa05 | ||
![]() |
7e0b7aff2a | ||
![]() |
6c450dcb09 | ||
![]() |
227f44283f | ||
![]() |
74f6e79625 | ||
![]() |
cec43e2ce8 | ||
![]() |
7553b258bb |
@@ -21,7 +21,7 @@
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.4" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.0" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.189" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.191" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
|
||||
|
@@ -32,7 +32,7 @@ public class TimeTick
|
||||
/// <summary>
|
||||
/// 上次触发时间
|
||||
/// </summary>
|
||||
public DateTime LastTime { get; private set; } = DateTime.Now;
|
||||
public DateTime LastTime { get; private set; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// 是否触发时间刻度
|
||||
@@ -62,7 +62,7 @@ public class TimeTick
|
||||
return result;
|
||||
}
|
||||
|
||||
public DateTime GetNextTime(DateTime currentTime, bool setLastTime = true)
|
||||
public DateTime GetNextTime(DateTime currentTime, bool setLastTime = false)
|
||||
{
|
||||
// 在没有 Cron 表达式的情况下,使用固定间隔
|
||||
if (cron == null)
|
||||
@@ -86,7 +86,7 @@ public class TimeTick
|
||||
|
||||
}
|
||||
|
||||
public DateTime GetNextTime(bool setLastTime = true) => GetNextTime(DateTime.UtcNow, setLastTime);
|
||||
public DateTime GetNextTime(bool setLastTime = false) => GetNextTime(DateTime.UtcNow, setLastTime);
|
||||
|
||||
/// <summary>
|
||||
/// 是否到达设置的时间间隔
|
||||
|
@@ -22,12 +22,34 @@ public static class JSRuntimeExtensions
|
||||
/// 获取文化信息
|
||||
/// </summary>
|
||||
/// <param name="jsRuntime"></param>
|
||||
public static ValueTask<string> GetCulture(this IJSRuntime jsRuntime) => jsRuntime.InvokeAsync<string>("getCultureLocalStorage");
|
||||
public static async ValueTask<string> GetCulture(this IJSRuntime jsRuntime)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await jsRuntime.InvokeAsync<string>("getCultureLocalStorage");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置文化信息
|
||||
/// </summary>
|
||||
/// <param name="jsRuntime"></param>
|
||||
/// <param name="cultureName"></param>
|
||||
public static ValueTask SetCulture(this IJSRuntime jsRuntime, string cultureName) => jsRuntime.InvokeVoidAsync("setCultureLocalStorage", cultureName);
|
||||
public static async ValueTask SetCulture(this IJSRuntime jsRuntime, string cultureName)
|
||||
{
|
||||
try
|
||||
{
|
||||
await jsRuntime.InvokeVoidAsync("setCultureLocalStorage", cultureName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.0.2" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.5.10" />
|
||||
<PackageReference Include="BootstrapBlazor" Version="9.6.0" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<PluginVersion>10.5.4</PluginVersion>
|
||||
<ProPluginVersion>10.5.4</ProPluginVersion>
|
||||
<PluginVersion>10.5.12</PluginVersion>
|
||||
<ProPluginVersion>10.5.12</ProPluginVersion>
|
||||
<AuthenticationVersion>2.1.7</AuthenticationVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CS-Script" Version="4.9.5" />
|
||||
<PackageReference Include="CS-Script" Version="4.9.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -97,9 +97,17 @@ public abstract class DeviceBase : DisposableObject, IDevice
|
||||
Channel.Stoping.Add(ChannelStoping);
|
||||
Channel.Started.Add(ChannelStarted);
|
||||
Channel.ChannelReceived.Add(ChannelReceived);
|
||||
|
||||
|
||||
SetChannel();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetChannel()
|
||||
{
|
||||
Channel.ChannelOptions.MaxConcurrentCount = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
~DeviceBase()
|
||||
{
|
||||
|
@@ -10,8 +10,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.4" />
|
||||
<PackageReference Include="TouchSocket" Version="3.1.0" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.1.0" />
|
||||
<PackageReference Include="TouchSocket" Version="3.1.1" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -87,12 +87,12 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
// 触发一次设备状态变化和变量值变化事件
|
||||
CollectDevices?.ForEach(a =>
|
||||
{
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine)
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
|
||||
});
|
||||
IdVariableRuntimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
@@ -85,12 +85,12 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
|
||||
CollectDevices?.ForEach(a =>
|
||||
{
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine)
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
|
||||
});
|
||||
IdVariableRuntimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBa
|
||||
// 触发一次变量值变化事件
|
||||
IdVariableRuntimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
@@ -51,6 +51,13 @@ public class Variable : BaseDataEntity, IValidatableObject
|
||||
[Required]
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 采集组
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "采集组", IsNullable = true)]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true, Order = 1)]
|
||||
public virtual string CollectGroup { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分组名称
|
||||
/// </summary>
|
||||
|
@@ -97,6 +97,7 @@
|
||||
"Name": "Name",
|
||||
"Description": "Description",
|
||||
"Group": "Group",
|
||||
"CollectGroup": "CollectGroup",
|
||||
"DeviceId": "CollectionDevice",
|
||||
"DeviceId.MinValue": "{0} cannot be empty",
|
||||
"DeviceId.Required": "{0} cannot be empty",
|
||||
@@ -452,6 +453,7 @@
|
||||
"Name.Required": "{0} cannot be empty",
|
||||
"Description": "Description",
|
||||
"Group": "Group",
|
||||
"CollectGroup": "CollectGroup",
|
||||
"DeviceId": "CollectionDevice",
|
||||
"DeviceId.MinValue": "{0} cannot be empty",
|
||||
"DeviceId.Required": "{0} cannot be empty",
|
||||
|
@@ -89,7 +89,8 @@
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"Description": "描述",
|
||||
"Group": "分组",
|
||||
"Group": "业务组",
|
||||
"CollectGroup": "采集组",
|
||||
"DeviceId": "采集设备",
|
||||
"DeviceId.MinValue": " {0} 不可为空",
|
||||
"DeviceId.Required": " {0} 不可为空",
|
||||
@@ -486,7 +487,8 @@
|
||||
"Name": "名称",
|
||||
"Name.Required": " {0} 不可为空",
|
||||
"Description": "描述",
|
||||
"Group": "分组",
|
||||
"Group": "业务组",
|
||||
"CollectGroup": "采集组",
|
||||
"DeviceId": "采集设备",
|
||||
"DeviceId.MinValue": " {0} 不可为空",
|
||||
"DeviceId.Required": " {0} 不可为空",
|
||||
|
@@ -175,7 +175,7 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
|
||||
if (a.Value.BindUrl == BindUrl)
|
||||
return true;
|
||||
if (a.Value.ChannelType == ChannelTypeEnum.UdpSession)
|
||||
if (a.Value.BindUrl == BindUrl)
|
||||
if ((!BindUrl.IsNullOrWhiteSpace()) && a.Value.BindUrl == BindUrl)
|
||||
return true;
|
||||
if (a.Value.ChannelType == ChannelTypeEnum.SerialPort)
|
||||
if (a.Value.PortName == PortName)
|
||||
|
@@ -26,7 +26,7 @@ namespace ThingsGateway.Gateway.Application;
|
||||
public class DeviceRuntime : Device, IDisposable
|
||||
{
|
||||
protected volatile DeviceStatusEnum _deviceStatus = DeviceStatusEnum.Default;
|
||||
|
||||
|
||||
private string? _lastErrorMessage;
|
||||
|
||||
/// <summary>
|
||||
|
@@ -19,5 +19,8 @@ public class VariableMapper : IRegister
|
||||
{
|
||||
config.ForType<Variable, VariableRuntime>()
|
||||
.Map(dest => dest.Value, src => src.InitValue);
|
||||
|
||||
config.ForType<VariableRuntime, VariableRuntime>()
|
||||
.Ignore(dest => dest.DeviceRuntime);
|
||||
}
|
||||
}
|
||||
|
@@ -8,8 +8,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.0" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.0" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.0" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.1" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.1" />
|
||||
<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />
|
||||
|
||||
</ItemGroup>
|
||||
|
@@ -1299,7 +1299,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
|
||||
try
|
||||
{
|
||||
if (Disposed) return;
|
||||
await Task.Delay(2000);
|
||||
await Task.Delay(1000);
|
||||
await OnClickSearch(SearchText);
|
||||
|
||||
Value = GetValue(Value);
|
||||
|
@@ -44,6 +44,7 @@
|
||||
<EditorItem @bind-Field="@context.Name" Readonly=BatchEditEnable />
|
||||
|
||||
<EditorItem @bind-Field="@context.Description" />
|
||||
<EditorItem @bind-Field="@context.CollectGroup" />
|
||||
<EditorItem @bind-Field="@context.Group" />
|
||||
|
||||
<EditorItem @bind-Field="@context.Unit" />
|
||||
|
@@ -212,8 +212,8 @@ public partial class VariableEditComponent
|
||||
{
|
||||
var component = new BootstrapDynamicComponent(data.VariablePropertyUIType, new Dictionary<string, object?>
|
||||
{
|
||||
[nameof(VariableEditComponent.Model)] = Model,
|
||||
[nameof(DeviceEditComponent.PluginPropertyEditorItems)] = data.EditorItems,
|
||||
[nameof(IPropertyUIBase.Model)] = Model,
|
||||
[nameof(IPropertyUIBase.PluginPropertyEditorItems)] = data.EditorItems,
|
||||
});
|
||||
VariablePropertyRenderFragments.AddOrUpdate(id, component.Render());
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.3" />
|
||||
<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.4" />
|
||||
<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.7" />
|
||||
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.1" />
|
||||
<ProjectReference Include="..\..\Admin\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />
|
||||
|
@@ -19,7 +19,7 @@ public class DeviceChangedTriggerNode : TextNode, ITriggerNode, IDisposable
|
||||
{
|
||||
Func = func;
|
||||
FuncDict.Add(this, func);
|
||||
if (!DeviceChangedTriggerNodeDict.TryGetValue(Text, out var list))
|
||||
if (!DeviceChangedTriggerNodeDict.TryGetValue(Text ?? string.Empty, out var list))
|
||||
{
|
||||
var deviceChangedTriggerNodes = new ConcurrentList<DeviceChangedTriggerNode>();
|
||||
deviceChangedTriggerNodes.Add(this);
|
||||
@@ -44,7 +44,7 @@ public class DeviceChangedTriggerNode : TextNode, ITriggerNode, IDisposable
|
||||
|
||||
private static void GlobalData_DeviceStatusChangeEvent(DeviceRuntime deviceRunTime, DeviceBasicData deviceData)
|
||||
{
|
||||
if (DeviceChangedTriggerNodeDict.TryGetValue(deviceData.Name, out var deviceChangedTriggerNodes) && deviceChangedTriggerNodes?.Count > 0)
|
||||
if (DeviceChangedTriggerNodeDict.TryGetValue(deviceData.Name ?? string.Empty, out var deviceChangedTriggerNodes) && deviceChangedTriggerNodes?.Count > 0)
|
||||
{
|
||||
if (!DeviceDatas.IsAddingCompleted)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ public class DeviceChangedTriggerNode : TextNode, ITriggerNode, IDisposable
|
||||
return DeviceDatas.GetConsumingEnumerable().ParallelForEachAsync((async (deviceDatas, token) =>
|
||||
{
|
||||
|
||||
if (DeviceChangedTriggerNodeDict.TryGetValue(deviceDatas.Name, out var valueChangedTriggerNodes))
|
||||
if (DeviceChangedTriggerNodeDict.TryGetValue(deviceDatas.Name ?? string.Empty, out var valueChangedTriggerNodes))
|
||||
{
|
||||
await valueChangedTriggerNodes.ParallelForEachAsync(async (item, token) =>
|
||||
{
|
||||
@@ -89,7 +89,7 @@ public class DeviceChangedTriggerNode : TextNode, ITriggerNode, IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
FuncDict.Remove(this);
|
||||
if (DeviceChangedTriggerNodeDict.TryGetValue(Text, out var list))
|
||||
if (DeviceChangedTriggerNodeDict.TryGetValue(Text ?? string.Empty, out var list))
|
||||
{
|
||||
list.Remove(this);
|
||||
}
|
||||
|
@@ -160,9 +160,19 @@ public class OpcDaMaster : IDisposable
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, List<OpcItem>> AddItemsWithSave(List<string> items)
|
||||
{
|
||||
int i = 0;
|
||||
ItemDicts = items.ConvertAll(o => new OpcItem(o)).ChunkTrivialBetter(OpcDaProperty.GroupSize).ToDictionary(a => "default" + (i++));
|
||||
return ItemDicts;
|
||||
lock (this)
|
||||
{
|
||||
|
||||
int i = ItemDicts.Count;
|
||||
var addItems = items.ConvertAll(o => new OpcItem(o)).ChunkTrivialBetter(OpcDaProperty.GroupSize).ToDictionary(a => "default" + (i++));
|
||||
|
||||
foreach (var item in addItems)
|
||||
{
|
||||
ItemDicts.TryAdd(item.Key, item.Value);
|
||||
}
|
||||
|
||||
return addItems;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -251,7 +251,7 @@ public class OpcUaMaster : IDisposable
|
||||
DisplayName = subscriptionName
|
||||
};
|
||||
List<MonitoredItem> monitoredItems = new();
|
||||
var variableNodes = loadType ? await ReadNodesAsync(items, cancellationToken).ConfigureAwait(false) : null;
|
||||
var variableNodes = loadType ? await ReadNodesAsync(items, false, cancellationToken).ConfigureAwait(false) : null;
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
try
|
||||
@@ -743,7 +743,7 @@ public class OpcUaMaster : IDisposable
|
||||
NodeId = new NodeId(item.Key),
|
||||
AttributeId = Attributes.Value,
|
||||
};
|
||||
var variableNode = await ReadNodeAsync(item.Key, false, cancellationToken).ConfigureAwait(false);
|
||||
var variableNode = await ReadNodeAsync(item.Key, false, false, cancellationToken).ConfigureAwait(false);
|
||||
var dataValue = JsonUtils.Decode(
|
||||
m_session.MessageContext,
|
||||
variableNode.DataType,
|
||||
@@ -793,9 +793,10 @@ public class OpcUaMaster : IDisposable
|
||||
{
|
||||
if (m_session != null)
|
||||
{
|
||||
var variableNode = ReadNode(monitoreditem.StartNodeId.ToString(), false);
|
||||
foreach (var value in monitoreditem.DequeueValues())
|
||||
{
|
||||
var variableNode = ReadNode(monitoreditem.StartNodeId.ToString(), false, StatusCode.IsGood(value.StatusCode));
|
||||
|
||||
if (value.Value != null)
|
||||
{
|
||||
var data = JsonUtils.Encode(m_session.MessageContext, TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable), value.Value);
|
||||
@@ -974,7 +975,7 @@ public class OpcUaMaster : IDisposable
|
||||
List<(string, DataValue, JToken)> jTokens = new();
|
||||
for (int i = 0; i < results.Count; i++)
|
||||
{
|
||||
var variableNode = await ReadNodeAsync(nodeIds[i].ToString(), false, cancellationToken).ConfigureAwait(false);
|
||||
var variableNode = await ReadNodeAsync(nodeIds[i].ToString(), false, StatusCode.IsGood(results[i].StatusCode), cancellationToken).ConfigureAwait(false);
|
||||
var type = TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable);
|
||||
var jToken = JsonUtils.Encode(m_session.MessageContext, type, results[i].Value);
|
||||
jTokens.Add((variableNode.NodeId.ToString(), results[i], jToken));
|
||||
@@ -985,7 +986,7 @@ public class OpcUaMaster : IDisposable
|
||||
/// <summary>
|
||||
/// 从服务器或缓存读取节点
|
||||
/// </summary>
|
||||
private VariableNode ReadNode(string nodeIdStr, bool isOnlyServer = true)
|
||||
private VariableNode ReadNode(string nodeIdStr, bool isOnlyServer = true, bool cache = true)
|
||||
{
|
||||
if (!isOnlyServer)
|
||||
{
|
||||
@@ -1025,14 +1026,15 @@ public class OpcUaMaster : IDisposable
|
||||
|
||||
VariableNode variableNode = GetVariableNodes(itemsToRead, values, diagnosticInfos, responseHeader).FirstOrDefault();
|
||||
|
||||
_variableDicts.AddOrUpdate(nodeIdStr, a => variableNode, (a, b) => variableNode);
|
||||
if (cache)
|
||||
_variableDicts.AddOrUpdate(nodeIdStr, a => variableNode, (a, b) => variableNode);
|
||||
return variableNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从服务器或缓存读取节点
|
||||
/// </summary>
|
||||
private async Task<VariableNode> ReadNodeAsync(string nodeIdStr, bool isOnlyServer = true, CancellationToken cancellationToken = default)
|
||||
private async Task<VariableNode> ReadNodeAsync(string nodeIdStr, bool isOnlyServer = true, bool cache = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!isOnlyServer)
|
||||
{
|
||||
@@ -1073,7 +1075,9 @@ public class OpcUaMaster : IDisposable
|
||||
|
||||
if (OpcUaProperty.LoadType && variableNode.DataType != NodeId.Null && TypeInfo.GetBuiltInType(variableNode.DataType, m_session.SystemContext.TypeTable) == BuiltInType.ExtensionObject)
|
||||
await typeSystem.LoadType(variableNode.DataType, ct: cancellationToken).ConfigureAwait(false);
|
||||
_variableDicts.AddOrUpdate(nodeIdStr, a => variableNode, (a, b) => variableNode);
|
||||
|
||||
if (cache)
|
||||
_variableDicts.AddOrUpdate(nodeIdStr, a => variableNode, (a, b) => variableNode);
|
||||
return variableNode;
|
||||
}
|
||||
|
||||
@@ -1127,7 +1131,7 @@ public class OpcUaMaster : IDisposable
|
||||
/// <summary>
|
||||
/// 从服务器读取节点
|
||||
/// </summary>
|
||||
private async Task<List<Node>> ReadNodesAsync(string[] nodeIdStrs, CancellationToken cancellationToken = default)
|
||||
private async Task<List<Node>> ReadNodesAsync(string[] nodeIdStrs, bool cache = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
List<Node> result = new(nodeIdStrs.Length);
|
||||
foreach (var items in nodeIdStrs.ChunkBetter(OpcUaProperty.GroupSize))
|
||||
@@ -1171,7 +1175,8 @@ public class OpcUaMaster : IDisposable
|
||||
}
|
||||
else
|
||||
{
|
||||
_variableDicts.AddOrUpdate(nodeIdStrs[i], a => node, (a, b) => node);
|
||||
if (cache)
|
||||
_variableDicts.AddOrUpdate(nodeIdStrs[i], a => node, (a, b) => node);
|
||||
if (node.DataType != NodeId.Null && TypeInfo.GetBuiltInType(node.DataType, m_session.SystemContext.TypeTable) == BuiltInType.ExtensionObject)
|
||||
{
|
||||
await typeSystem.LoadType(node.DataType, ct: cancellationToken).ConfigureAwait(false);
|
||||
|
@@ -12,7 +12,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.8" GeneratePathProperty="true">
|
||||
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.11" GeneratePathProperty="true">
|
||||
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
|
@@ -1,32 +1,11 @@
|
||||
<Project>
|
||||
|
||||
|
||||
|
||||
<Target Name="CopyNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<!-- setting up the variable for convenience -->
|
||||
<ApplicationPackageFiles Include="$(PkgMQTTnet_AspNetCore)\lib\net6.0\*.*" />
|
||||
<MQTTnetApplicationPackageFiles Include="$(PkgMQTTnet)\lib\net6.0\*.*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net6.0'">
|
||||
<!-- setting up the variable for convenience -->
|
||||
<ApplicationPackageFiles Include="$(PkgMQTTnet_AspNetCore)\lib\net8.0\*.*" />
|
||||
<MQTTnet_ServerApplicationPackageFiles Include="$(PkgMQTTnet_Server)\lib\net8.0\*.*" />
|
||||
<MQTTnetApplicationPackageFiles Include="$(PkgMQTTnet)\lib\net8.0\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationFolder>$(TargetDir)</ApplicationFolder>
|
||||
</PropertyGroup>
|
||||
<Copy SourceFiles="@(ApplicationPackageFiles)" DestinationFolder="$(ApplicationFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(MQTTnet_ServerApplicationPackageFiles)" DestinationFolder="$(ApplicationFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(MQTTnetApplicationPackageFiles)" DestinationFolder="$(ApplicationFolder)%(RecursiveDir)" />
|
||||
</Target>
|
||||
|
||||
|
||||
<!--在构建后触发的。它通过在 Nuget 包的 Content 文件夹中包含目标目录中的所有文件和子文件夹来创建 nuget 包-->
|
||||
<Target Name="IncludeAllFilesInTargetDir" AfterTargets="Build">
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(ProjectDir)bin\$(Configuration)\$(TargetFramework)\**\*MQTT*.dll">
|
||||
<Content Include="$(ProjectDir)bin\$(Configuration)\$(TargetFramework)\**\*Http*.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>Content</PackagePath>
|
||||
</Content>
|
||||
|
@@ -80,6 +80,11 @@ public class ModbusMaster : CollectFoundationBase
|
||||
protected override async Task<List<VariableSourceRead>> ProtectedLoadSourceReadAsync(List<VariableRuntime> deviceVariables)
|
||||
{
|
||||
await Task.CompletedTask.ConfigureAwait(false);
|
||||
return _plc.LoadSourceRead<VariableSourceRead>(deviceVariables, _driverPropertys.MaxPack, CurrentDevice.IntervalTime);
|
||||
List<VariableSourceRead> variableSourceReads = new();
|
||||
foreach (var deviceVariable in deviceVariables.GroupBy(a => a.CollectGroup))
|
||||
{
|
||||
variableSourceReads.AddRange(_plc.LoadSourceRead<VariableSourceRead>(deviceVariable, _driverPropertys.MaxPack, CurrentDevice.IntervalTime));
|
||||
}
|
||||
return variableSourceReads;
|
||||
}
|
||||
}
|
||||
|
@@ -122,25 +122,31 @@ public class OpcDaMaster : CollectBase
|
||||
{
|
||||
if (deviceVariables.Count > 0)
|
||||
{
|
||||
var result = _plc.AddItemsWithSave(deviceVariables.Where(a => !string.IsNullOrEmpty(a.RegisterAddress)).Select(a => a.RegisterAddress!).ToList());
|
||||
var sourVars = result?.Select(
|
||||
it =>
|
||||
{
|
||||
var read = new VariableSourceRead()
|
||||
{
|
||||
TimeTick = new(_driverProperties.UpdateRate.ToString()),
|
||||
RegisterAddress = it.Key,
|
||||
};
|
||||
HashSet<string> ids = new(it.Value.Select(b => b.ItemID));
|
||||
List<VariableSourceRead> variableSourceReads = new List<VariableSourceRead>();
|
||||
foreach (var deviceVariableGroups in deviceVariables.GroupBy(a => a.CollectGroup))
|
||||
{
|
||||
|
||||
var variables = deviceVariables.Where(a => ids.Contains(a.RegisterAddress));
|
||||
foreach (var v in variables)
|
||||
var result = _plc.AddItemsWithSave(deviceVariableGroups.Where(a => !string.IsNullOrEmpty(a.RegisterAddress)).Select(a => a.RegisterAddress!).ToList());
|
||||
var sourVars = result?.Select(
|
||||
it =>
|
||||
{
|
||||
read.AddVariable(v);
|
||||
}
|
||||
return read;
|
||||
}).ToList();
|
||||
return sourVars;
|
||||
var read = new VariableSourceRead()
|
||||
{
|
||||
TimeTick = new(_driverProperties.UpdateRate.ToString()),
|
||||
RegisterAddress = it.Key,
|
||||
};
|
||||
HashSet<string> ids = new(it.Value.Select(b => b.ItemID));
|
||||
|
||||
var variables = deviceVariableGroups.Where(a => ids.Contains(a.RegisterAddress));
|
||||
foreach (var v in variables)
|
||||
{
|
||||
read.AddVariable(v);
|
||||
}
|
||||
return read;
|
||||
}).ToList();
|
||||
variableSourceReads.AddRange(sourVars);
|
||||
}
|
||||
return variableSourceReads;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -187,24 +187,27 @@ public class OpcUaMaster : CollectBase
|
||||
await Task.CompletedTask.ConfigureAwait(false);
|
||||
if (deviceVariables.Count > 0)
|
||||
{
|
||||
var dataLists = deviceVariables.ChunkBetter(_driverProperties.GroupSize);
|
||||
|
||||
var dataResult = new List<VariableSourceRead>();
|
||||
foreach (var variable in dataLists)
|
||||
List<VariableSourceRead> variableSourceReads = new List<VariableSourceRead>();
|
||||
foreach (var deviceVariableGroups in deviceVariables.GroupBy(a => a.CollectGroup))
|
||||
{
|
||||
var sourVars = new VariableSourceRead()
|
||||
{
|
||||
TimeTick = new(_driverProperties.UpdateRate.ToString()),
|
||||
RegisterAddress = Guid.NewGuid().ToString(),
|
||||
};
|
||||
foreach (var item in variable)
|
||||
{
|
||||
sourVars.AddVariable(item);
|
||||
}
|
||||
dataResult.Add(sourVars);
|
||||
}
|
||||
var dataLists = deviceVariableGroups.ChunkBetter(_driverProperties.GroupSize);
|
||||
|
||||
return dataResult;
|
||||
foreach (var variable in dataLists)
|
||||
{
|
||||
var sourVars = new VariableSourceRead()
|
||||
{
|
||||
TimeTick = new(_driverProperties.UpdateRate.ToString()),
|
||||
RegisterAddress = Guid.NewGuid().ToString(),
|
||||
};
|
||||
foreach (var item in variable)
|
||||
{
|
||||
sourVars.AddVariable(item);
|
||||
}
|
||||
variableSourceReads.Add(sourVars);
|
||||
}
|
||||
|
||||
}
|
||||
return variableSourceReads;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -221,7 +221,12 @@ public class SiemensS7Master : CollectFoundationBase
|
||||
{
|
||||
|
||||
}
|
||||
return _plc.LoadSourceRead<VariableSourceRead>(deviceVariables, _plc.OnLine ? _plc.PduLength : _driverPropertys.MaxPack, CurrentDevice.IntervalTime);
|
||||
List<VariableSourceRead> variableSourceReads = new();
|
||||
foreach (var deviceVariable in deviceVariables.GroupBy(a => a.CollectGroup))
|
||||
{
|
||||
variableSourceReads.AddRange(_plc.LoadSourceRead<VariableSourceRead>(deviceVariable, _driverPropertys.MaxPack, CurrentDevice.IntervalTime));
|
||||
}
|
||||
return variableSourceReads;
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
"ConfigurationScanDirectories": [ "Configuration", "" ], // 扫描配置文件json文件夹(自动合并该文件夹里面所有json文件)
|
||||
"IgnoreConfigurationFiles": [ "" ],
|
||||
"ExternalAssemblies": [ "" ]
|
||||
"ExternalAssemblies": [ "" ],
|
||||
"DetailedErrors": true
|
||||
|
||||
}
|
||||
|
@@ -162,7 +162,7 @@ public class FileHostService : BackgroundService, IFileHostService
|
||||
_log.Exception(ex);
|
||||
try
|
||||
{
|
||||
await TcpDmtpService.StopAsync().ConfigureAwait(false);
|
||||
await TcpDmtpService.StopAsync(default).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.0" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>10.5.4</Version>
|
||||
<Version>10.5.12</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
Reference in New Issue
Block a user