Compare commits

..

11 Commits

Author SHA1 Message Date
2248356998 qq.com
b790cf5f4e 更新依赖 2025-05-05 20:25:43 +08:00
Diego
d1248811fd build: 10.5.11 2025-04-30 23:05:36 +08:00
2248356998 qq.com
022d016e8e feat: 添加采集组 2025-04-30 23:04:51 +08:00
Diego
f73245e650 build: 10.5.10 2025-04-30 15:31:39 +08:00
2248356998 qq.com
484461fa05 更新依赖 2025-04-30 15:29:19 +08:00
Diego
7e0b7aff2a feat: sqldb支持数组 2025-04-28 15:52:32 +08:00
Diego
6c450dcb09 feat: sqldb支持数组类型 2025-04-28 15:52:11 +08:00
Diego
227f44283f build: 10.5.8 2025-04-28 15:30:10 +08:00
Diego
74f6e79625 build: 10.5.7
优化opcua变量缓存
修复cron表达式间隔
2025-04-27 16:35:58 +08:00
Diego
cec43e2ce8 feat: 防呆设计,强制设置通道的最大并发数 2025-04-27 10:13:35 +08:00
Diego
7553b258bb build: 10.5.5 2025-04-26 17:46:31 +08:00
36 changed files with 167 additions and 108 deletions

View File

@@ -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" />

View File

@@ -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>
/// 是否到达设置的时间间隔

View File

@@ -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
{
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CS-Script" Version="4.9.5" />
<PackageReference Include="CS-Script" Version="4.9.6" />
</ItemGroup>
<ItemGroup>

View File

@@ -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()
{

View File

@@ -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>

View File

@@ -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>());
});
}

View File

@@ -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>());
});
}

View File

@@ -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>());
});
}

View File

@@ -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>

View File

@@ -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",

View File

@@ -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} 不可为空",

View File

@@ -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)

View File

@@ -26,7 +26,7 @@ namespace ThingsGateway.Gateway.Application;
public class DeviceRuntime : Device, IDisposable
{
protected volatile DeviceStatusEnum _deviceStatus = DeviceStatusEnum.Default;
private string? _lastErrorMessage;
/// <summary>

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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" />

View File

@@ -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());
}

View File

@@ -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" />

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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 { }
}

View File

@@ -3,6 +3,7 @@
"ConfigurationScanDirectories": [ "Configuration", "" ], // 扫描配置文件json文件夹自动合并该文件夹里面所有json文件
"IgnoreConfigurationFiles": [ "" ],
"ExternalAssemblies": [ "" ]
"ExternalAssemblies": [ "" ],
"DetailedErrors": true
}

View File

@@ -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
{

View File

@@ -16,7 +16,7 @@
<ItemGroup>
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.0" />
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.1" />
</ItemGroup>

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>10.5.4</Version>
<Version>10.5.12</Version>
</PropertyGroup>
<ItemGroup>