Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bb9cd7419 | ||
|
|
ba008ef8ba | ||
|
|
28b533decf | ||
|
|
9ee638c2f1 | ||
|
|
d90fdbaf35 | ||
|
|
b55e3db736 | ||
|
|
dbee8496cb | ||
|
|
044e78bea9 | ||
|
|
fe79128d90 | ||
|
|
34120da008 |
@@ -38,7 +38,7 @@
|
||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<!--<PackageReference Include="Mapster" Version="7.4.0" />-->
|
||||
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.5.4" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
|
||||
@@ -466,7 +466,14 @@ public class DefaultConvert
|
||||
|
||||
if (value is Double d)
|
||||
{
|
||||
return Double.IsNaN(d) ? defaultValue : (Decimal)d;
|
||||
try
|
||||
{
|
||||
return Double.IsNaN(d) ? defaultValue : (Decimal)d;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
using ThingsGateway.NewLife.Collections;
|
||||
|
||||
namespace ThingsGateway.NewLife.DictionaryExtensions;
|
||||
|
||||
/// <summary>并发字典扩展</summary>
|
||||
@@ -105,57 +103,6 @@ public static class DictionaryExtensions
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量出队
|
||||
/// </summary>
|
||||
public static IEnumerable<T> ToIEnumerableWithDequeue<TKEY, T>(this ConcurrentDictionary<TKEY, T> 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, out var result))
|
||||
{
|
||||
yield return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -187,6 +134,7 @@ public static class DictionaryExtensions
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量出队
|
||||
/// </summary>
|
||||
@@ -214,4 +162,9 @@ public static class DictionaryExtensions
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<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>
|
||||
<NET9Version>9.0.6</NET9Version>
|
||||
<PluginVersion>10.9.35</PluginVersion>
|
||||
<ProPluginVersion>10.9.35</ProPluginVersion>
|
||||
<DefaultVersion>10.9.35</DefaultVersion>
|
||||
<AuthenticationVersion>2.9.16</AuthenticationVersion>
|
||||
<SourceGeneratorVersion>10.9.15</SourceGeneratorVersion>
|
||||
<NET8Version>8.0.18</NET8Version>
|
||||
<NET9Version>9.0.7</NET9Version>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ public static class CSharpScriptEngineExtension
|
||||
/// </summary>
|
||||
public static T Do<T>(string source, params Assembly[] assemblies) where T : class
|
||||
{
|
||||
if (source.IsNullOrEmpty()) return null;
|
||||
var field = $"{CacheKey}-{source}";
|
||||
var runScript = Instance.Get<T>(field);
|
||||
if (runScript == null)
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="$(NET9Version)" />
|
||||
<PackageReference Include="TouchSocket" Version="3.1.11" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.1.11" />
|
||||
<PackageReference Include="TouchSocket" Version="3.1.12" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.1.12" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -39,7 +39,8 @@ public interface IThingsGatewayBitConverter
|
||||
|
||||
[JsonProperty(ItemConverterType = typeof(NewtonsoftEncodingConverter))]
|
||||
#endif
|
||||
Encoding Encoding { get; set; }
|
||||
public Encoding? Encoding { get; set; }
|
||||
public Encoding EncodingValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前的Bcd编码类型
|
||||
|
||||
@@ -29,13 +29,16 @@ public partial class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(EncodingConverter))]
|
||||
[JsonConverter(typeof(NewtonsoftEncodingConverter))]
|
||||
public Encoding Encoding { get; set; } = Encoding.UTF8;
|
||||
public Encoding? Encoding { get; set; }
|
||||
#else
|
||||
|
||||
[JsonConverter(typeof(NewtonsoftEncodingConverter))]
|
||||
public Encoding Encoding { get; set; } = Encoding.UTF8;
|
||||
public Encoding? Encoding { get; set; }
|
||||
|
||||
#endif
|
||||
|
||||
public Encoding EncodingValue => Encoding ?? Encoding.UTF8;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DataFormatEnum DataFormat { get; set; }
|
||||
|
||||
@@ -239,7 +242,7 @@ public partial class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] bytes = Encoding.GetBytes(value);
|
||||
byte[] bytes = EncodingValue.GetBytes(value);
|
||||
return IsStringReverseByteWord ? bytes.BytesReverseByWord().ArrayExpandToLength(StringLength.Value) : bytes.ArrayExpandToLength(StringLength.Value);
|
||||
}
|
||||
}
|
||||
@@ -252,7 +255,7 @@ public partial class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] bytes = Encoding.GetBytes(value);
|
||||
byte[] bytes = EncodingValue.GetBytes(value);
|
||||
return IsStringReverseByteWord ? bytes.BytesReverseByWord() : bytes;
|
||||
}
|
||||
}
|
||||
@@ -366,8 +369,8 @@ public partial class ThingsGatewayBitConverter : IThingsGatewayBitConverter
|
||||
else
|
||||
{
|
||||
return IsStringReverseByteWord ?
|
||||
Encoding.GetString(new ReadOnlySpan<byte>(buffer, offset, len).ToArray().BytesReverseByWord()).TrimEnd().Replace($"\0", "") :
|
||||
Encoding.GetString(buffer, offset, len).TrimEnd().Replace($"\0", "");
|
||||
EncodingValue.GetString(new ReadOnlySpan<byte>(buffer, offset, len).ToArray().BytesReverseByWord()).TrimEnd().Replace($"\0", "") :
|
||||
EncodingValue.GetString(buffer, offset, len).TrimEnd().Replace($"\0", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ public abstract class BusinessBaseWithCache : BusinessBase
|
||||
{
|
||||
if (_memoryAlarmModelQueue.Count > _businessPropertyWithCache.QueueMaxCount)
|
||||
{
|
||||
LogMessage?.LogWarning($"{typeof(AlarmVariable).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase [QueueMaxCount] or Enable cache");
|
||||
LogMessage?.LogWarning($"{typeof(AlarmVariable).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase {_businessPropertyWithCache.QueueMaxCount} or Enable cache");
|
||||
_memoryAlarmModelQueue.Clear();
|
||||
_memoryAlarmModelQueue.Enqueue(data);
|
||||
return;
|
||||
@@ -405,7 +405,7 @@ public abstract class BusinessBaseWithCache : BusinessBase
|
||||
{
|
||||
if (_memoryDevModelQueue.Count > _businessPropertyWithCache.QueueMaxCount)
|
||||
{
|
||||
LogMessage?.LogWarning($"{typeof(DeviceBasicData).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase [QueueMaxCount] or Enable cache");
|
||||
LogMessage?.LogWarning($"{typeof(DeviceBasicData).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase {_businessPropertyWithCache.QueueMaxCount} or Enable cache");
|
||||
_memoryDevModelQueue.Clear();
|
||||
_memoryDevModelQueue.Enqueue(data);
|
||||
return;
|
||||
@@ -685,7 +685,7 @@ public abstract class BusinessBaseWithCache : BusinessBase
|
||||
{
|
||||
if (_memoryVarModelQueue.Count > _businessPropertyWithCache.QueueMaxCount)
|
||||
{
|
||||
LogMessage?.LogWarning($"{typeof(VariableBasicData).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase [QueueMaxCount] or Enable cache");
|
||||
LogMessage?.LogWarning($"{typeof(VariableBasicData).Name} Queue exceeds limit, clear old data. If it doesn't work as expected, increase {_businessPropertyWithCache.QueueMaxCount} or Enable cache");
|
||||
_memoryVarModelQueue.Clear();
|
||||
_memoryVarModelQueue.Enqueue(data);
|
||||
return;
|
||||
|
||||
@@ -91,7 +91,7 @@ public class ExecuteScriptNode : TextNode, IActuatorNode, IExexcuteExpressionsBa
|
||||
try
|
||||
{
|
||||
var exexcuteExpressions = CSharpScriptEngineExtension.Do<IExexcuteExpressions>(text);
|
||||
exexcuteExpressions.TryDispose();
|
||||
exexcuteExpressions?.TryDispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -110,6 +110,10 @@ public class ExecuteScriptNode : TextNode, IActuatorNode, IExexcuteExpressionsBa
|
||||
{
|
||||
Logger?.Trace($"Execute script");
|
||||
var exexcuteExpressions = CSharpScriptEngineExtension.Do<IExexcuteExpressions>(Text);
|
||||
if (exexcuteExpressions == null)
|
||||
{
|
||||
return new OperResult<NodeOutput>("exexcuteExpressions is null");
|
||||
}
|
||||
exexcuteExpressions.Logger = Logger;
|
||||
var data = await exexcuteExpressions.ExecuteAsync(input, cancellationToken).ConfigureAwait(false);
|
||||
return new OperResult<NodeOutput>() { Content = data };
|
||||
@@ -125,18 +129,19 @@ public class ExecuteScriptNode : TextNode, IActuatorNode, IExexcuteExpressionsBa
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (text.IsNullOrWhiteSpace())
|
||||
return;
|
||||
try
|
||||
{
|
||||
var exexcuteExpressions = CSharpScriptEngineExtension.Do<IExexcuteExpressions>(text);
|
||||
exexcuteExpressions.TryDispose();
|
||||
}
|
||||
catch
|
||||
if (!text.IsNullOrWhiteSpace())
|
||||
{
|
||||
try
|
||||
{
|
||||
var exexcuteExpressions = CSharpScriptEngineExtension.Do<IExexcuteExpressions>(text);
|
||||
exexcuteExpressions.TryDispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
CSharpScriptEngineExtension.Remove(text);
|
||||
}
|
||||
CSharpScriptEngineExtension.Remove(text);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.1" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.3" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.11" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.11" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.12" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.12" />
|
||||
<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />
|
||||
<!--<ProjectReference Include="..\..\PluginPro\ThingsGateway.Authentication\ThingsGateway.Authentication.csproj" />-->
|
||||
|
||||
|
||||
@@ -4,50 +4,66 @@ namespace ThingsGateway.Gateway.Razor
|
||||
{
|
||||
public static class TreeViewItemMapper
|
||||
{
|
||||
|
||||
public static global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>> AdaptListTreeViewItemChannelDeviceTreeItem(this global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>> src, global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> parent = null)
|
||||
public static global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>> AdaptListTreeViewItemChannelDeviceTreeItem(this global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>> src)
|
||||
{
|
||||
var target = new global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>>(src.Count);
|
||||
foreach (var item in src)
|
||||
NormalizeItems(src);
|
||||
return src.ToList();
|
||||
}
|
||||
static void NormalizeItems<T>(List<TreeViewItem<T>> nodes)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
target.Add(MapToTreeViewItemOfChannelDeviceTreeItem(item, parent));
|
||||
if (node.Items.Count > 0)
|
||||
{
|
||||
node.Items = node.Items.ToList();
|
||||
NormalizeItems(node.Items);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
//public static global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>> AdaptListTreeViewItemChannelDeviceTreeItem(this global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>> src, global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> parent = null)
|
||||
//{
|
||||
// var target = new global::System.Collections.Generic.List<global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>>(src.Count);
|
||||
// foreach (var item in src)
|
||||
// {
|
||||
// target.Add(MapToTreeViewItemOfChannelDeviceTreeItem(item, parent));
|
||||
// }
|
||||
// return target;
|
||||
//}
|
||||
|
||||
private static global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> MapToTreeViewItemOfChannelDeviceTreeItem(global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> source, global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> parent)
|
||||
{
|
||||
var target = new global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>(source.Value);
|
||||
target.CheckedState = source.CheckedState;
|
||||
target.Items = AdaptListTreeViewItemChannelDeviceTreeItem(source.Items.ToList(), target);
|
||||
if (source.Parent != null && parent != null)
|
||||
{
|
||||
target.Parent = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.Parent = null;
|
||||
}
|
||||
target.Text = source.Text;
|
||||
target.Icon = source.Icon;
|
||||
target.ExpandIcon = source.ExpandIcon;
|
||||
target.CssClass = source.CssClass;
|
||||
target.IsDisabled = source.IsDisabled;
|
||||
target.IsActive = source.IsActive;
|
||||
target.Template = source.Template;
|
||||
if (source.Value != null)
|
||||
{
|
||||
target.Value = source.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.Value = null;
|
||||
}
|
||||
target.IsExpand = source.IsExpand;
|
||||
target.HasChildren = source.HasChildren;
|
||||
return target;
|
||||
}
|
||||
|
||||
//private static global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> MapToTreeViewItemOfChannelDeviceTreeItem(global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> source, global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem> parent)
|
||||
//{
|
||||
// var target = new global::BootstrapBlazor.Components.TreeViewItem<global::ThingsGateway.Gateway.Razor.ChannelDeviceTreeItem>(source.Value);
|
||||
// target.CheckedState = source.CheckedState;
|
||||
// target.Items = AdaptListTreeViewItemChannelDeviceTreeItem(source.Items.ToList(), target);
|
||||
// if (source.Parent != null && parent != null)
|
||||
// {
|
||||
// target.Parent = parent;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// target.Parent = null;
|
||||
// }
|
||||
// target.Text = source.Text;
|
||||
// target.Icon = source.Icon;
|
||||
// target.ExpandIcon = source.ExpandIcon;
|
||||
// target.CssClass = source.CssClass;
|
||||
// target.IsDisabled = source.IsDisabled;
|
||||
// target.IsActive = source.IsActive;
|
||||
// target.Template = source.Template;
|
||||
// if (source.Value != null)
|
||||
// {
|
||||
// target.Value = source.Value;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// target.Value = null;
|
||||
// }
|
||||
// target.IsExpand = source.IsExpand;
|
||||
// target.HasChildren = source.HasChildren;
|
||||
// return target;
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1240,19 +1240,19 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
|
||||
UnknownTreeViewItem = new TreeViewItem<ChannelDeviceTreeItem>(UnknownItem)
|
||||
{
|
||||
Text = GatewayLocalizer["Unknown"],
|
||||
IsActive = Value == UnknownItem,
|
||||
IsActive = false,
|
||||
IsExpand = true,
|
||||
};
|
||||
ZItem = new List<TreeViewItem<ChannelDeviceTreeItem>>() {new TreeViewItem<ChannelDeviceTreeItem>(CollectItem)
|
||||
{
|
||||
Text = GatewayLocalizer["Collect"],
|
||||
IsActive = Value == CollectItem,
|
||||
IsActive = false,
|
||||
IsExpand = true,
|
||||
},
|
||||
new TreeViewItem<ChannelDeviceTreeItem>(BusinessItem)
|
||||
{
|
||||
Text = GatewayLocalizer["Business"],
|
||||
IsActive = Value == BusinessItem,
|
||||
IsActive = false,
|
||||
IsExpand = true,
|
||||
}};
|
||||
|
||||
@@ -1419,7 +1419,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
|
||||
{
|
||||
if (item.PluginType == PluginTypeEnum.Collect)
|
||||
collectChannelDevices.Add(item, new());
|
||||
else if (item.PluginType == PluginTypeEnum.Collect)
|
||||
else if (item.PluginType == PluginTypeEnum.Business)
|
||||
businessChannelDevices.Add(item, new());
|
||||
else
|
||||
otherChannelDevices.Add(item, new());
|
||||
@@ -1533,13 +1533,5 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
|
||||
private void OnUpdateCallbackAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,8 @@ public static class JsonUtils
|
||||
case BuiltInType.Int64: { return decoder.ReadInt64(fieldName); }
|
||||
case BuiltInType.UInt64: { return decoder.ReadUInt64(fieldName); }
|
||||
case BuiltInType.Float: { return decoder.ReadFloat(fieldName); }
|
||||
case BuiltInType.Double: { return decoder.ReadDouble(fieldName); }
|
||||
case BuiltInType.Double:
|
||||
case BuiltInType.Number: { return decoder.ReadDouble(fieldName); }
|
||||
case BuiltInType.String:
|
||||
{
|
||||
if (decoder.ReadField(fieldName, out var value))
|
||||
@@ -288,7 +289,7 @@ public static class JsonUtils
|
||||
}
|
||||
case BuiltInType.Number:
|
||||
{
|
||||
encoder.WriteInt64(fieldName, Convert.ToInt64(value));
|
||||
encoder.WriteDouble(fieldName, Convert.ToInt64(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.UInteger:
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace ThingsGateway.Foundation.SiemensS7;
|
||||
|
||||
internal static class PackHelper
|
||||
@@ -88,7 +86,7 @@ internal static class PackHelper
|
||||
|
||||
if (s7Address.WStringEnable)
|
||||
{
|
||||
it.ThingsGatewayBitConverter.Encoding = Encoding.Unicode;
|
||||
//it.ThingsGatewayBitConverter.Encoding = Encoding.Unicode;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -98,7 +96,7 @@ internal static class PackHelper
|
||||
// 字符串在S7中,前四个字节不属于实际内容
|
||||
it.Index += 4;
|
||||
lastLen = it.ThingsGatewayBitConverter.StringLength.Value + 4;
|
||||
it.ThingsGatewayBitConverter.Encoding = Encoding.BigEndianUnicode;
|
||||
//it.ThingsGatewayBitConverter.Encoding = Encoding.BigEndianUnicode;
|
||||
|
||||
}
|
||||
else if (it.ThingsGatewayBitConverter.IsVariableStringLength)
|
||||
|
||||
@@ -128,12 +128,12 @@ internal sealed partial class SiemensHelper
|
||||
|
||||
|
||||
|
||||
internal static async ValueTask<OperResult<string>> ReadWStringAsync(SiemensS7Master plc, string address, CancellationToken cancellationToken)
|
||||
internal static async ValueTask<OperResult<string>> ReadWStringAsync(SiemensS7Master plc, string address, Encoding encoding, CancellationToken cancellationToken)
|
||||
{
|
||||
//先读取一次获取长度,再读取实际值
|
||||
if (plc.SiemensS7Type != SiemensTypeEnum.S200Smart)
|
||||
{
|
||||
var encoding = Encoding.BigEndianUnicode;
|
||||
encoding ??= Encoding.BigEndianUnicode;
|
||||
var result1 = await plc.ReadAsync(address, 4, cancellationToken).ConfigureAwait(false);
|
||||
if (!result1.IsSuccess)
|
||||
{
|
||||
@@ -155,7 +155,7 @@ internal sealed partial class SiemensHelper
|
||||
}
|
||||
else
|
||||
{
|
||||
var encoding = Encoding.Unicode;
|
||||
encoding ??= Encoding.Unicode;
|
||||
var result1 = await plc.ReadAsync(address, 1, cancellationToken).ConfigureAwait(false);
|
||||
if (!result1.IsSuccess)
|
||||
return new OperResult<string>(result1);
|
||||
@@ -171,12 +171,12 @@ internal sealed partial class SiemensHelper
|
||||
}
|
||||
}
|
||||
|
||||
internal static async ValueTask<OperResult> WriteWStringAsync(SiemensS7Master plc, string address, string value, CancellationToken cancellationToken = default)
|
||||
internal static async ValueTask<OperResult> WriteWStringAsync(SiemensS7Master plc, string address, string value, Encoding encoding, CancellationToken cancellationToken = default)
|
||||
{
|
||||
value ??= string.Empty;
|
||||
if (plc.SiemensS7Type != SiemensTypeEnum.S200Smart)
|
||||
{
|
||||
byte[] inBytes1 = Encoding.BigEndianUnicode.GetBytes(value);
|
||||
byte[] inBytes1 = (encoding ?? Encoding.BigEndianUnicode).GetBytes(value);
|
||||
var result = await plc.ReadAsync(address, 4, cancellationToken).ConfigureAwait(false);
|
||||
if (!result.IsSuccess) return result;
|
||||
var num = plc.ThingsGatewayBitConverter.ToUInt16(result.Content, 0);
|
||||
@@ -189,7 +189,7 @@ internal sealed partial class SiemensHelper
|
||||
inBytes1
|
||||
), DataTypeEnum.String, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
byte[] inBytes2 = Encoding.Unicode.GetBytes(value);
|
||||
byte[] inBytes2 = (encoding ?? Encoding.Unicode).GetBytes(value);
|
||||
return await plc.WriteAsync(address, DataTransUtil.SpliceArray([(byte)value.Length], inBytes2), DataTypeEnum.String, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,7 +569,7 @@ public partial class SiemensS7Master : DeviceBase
|
||||
{
|
||||
return new OperResult<string[]>(AppResource.StringLengthReadError);
|
||||
}
|
||||
var result = await SiemensHelper.ReadWStringAsync(this, address, cancellationToken).ConfigureAwait(false);
|
||||
var result = await SiemensHelper.ReadWStringAsync(this, address, bitConverter.Encoding, cancellationToken).ConfigureAwait(false);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult(new string[] { result.Content });
|
||||
@@ -585,7 +585,7 @@ public partial class SiemensS7Master : DeviceBase
|
||||
{
|
||||
return new OperResult<string[]>(AppResource.StringLengthReadError);
|
||||
}
|
||||
var result = await SiemensHelper.ReadStringAsync(this, address, bitConverter.Encoding, cancellationToken).ConfigureAwait(false);
|
||||
var result = await SiemensHelper.ReadStringAsync(this, address, bitConverter.EncodingValue, cancellationToken).ConfigureAwait(false);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult(new string[] { result.Content });
|
||||
@@ -608,11 +608,11 @@ public partial class SiemensS7Master : DeviceBase
|
||||
|
||||
if (((S7BitConverter)bitConverter)?.WStringEnable == true)
|
||||
{
|
||||
return SiemensHelper.WriteWStringAsync(this, address, value, cancellationToken);
|
||||
return SiemensHelper.WriteWStringAsync(this, address, value, bitConverter.Encoding, cancellationToken);
|
||||
}
|
||||
if (bitConverter.IsVariableStringLength)
|
||||
{
|
||||
return SiemensHelper.WriteStringAsync(this, address, value, bitConverter.Encoding, cancellationToken);
|
||||
return SiemensHelper.WriteStringAsync(this, address, value, bitConverter.EncodingValue, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -147,9 +147,10 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariable, IDBH
|
||||
{
|
||||
if (_driverPropertys.IsReadDB)
|
||||
{
|
||||
var list = RealTimeVariables.ToListWithDequeue();
|
||||
try
|
||||
{
|
||||
var varLists = RealTimeVariables.ToIEnumerableWithDequeue().Batch(100000);
|
||||
var varLists = list.Batch(100000);
|
||||
foreach (var varList in varLists)
|
||||
{
|
||||
var result = await UpdateAsync(varList, cancellationToken).ConfigureAwait(false);
|
||||
@@ -166,6 +167,11 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariable, IDBH
|
||||
if (success)
|
||||
LogMessage?.LogWarning(ex);
|
||||
success = false;
|
||||
|
||||
list.ForEach(variable =>
|
||||
{
|
||||
RealTimeVariables.AddOrUpdate(variable.Id, variable, (key, oldValue) => variable);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public class ModbusSlave : BusinessBase
|
||||
{
|
||||
private readonly ModbusSlaveProperty _driverPropertys = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, VariableRuntime> ModbusVariableQueue = new();
|
||||
private readonly ConcurrentDictionary<string, long> ModbusVariableQueue = new();
|
||||
|
||||
private readonly ModbusSlaveVariableProperty _variablePropertys = new();
|
||||
|
||||
@@ -172,19 +172,22 @@ public class ModbusSlave : BusinessBase
|
||||
await Task.Delay(10000, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
var list = ModbusVariableQueue.ToIEnumerableKVWithDequeue();
|
||||
var list = ModbusVariableQueue.ToDictWithDequeue();
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
break;
|
||||
var type = item.Value.GetPropertyValue(CurrentDevice.Id, nameof(ModbusSlaveVariableProperty.DataType));
|
||||
if (!IdVariableRuntimes.TryGetValue(item.Value, out var variableRuntime))
|
||||
break;
|
||||
|
||||
var type = variableRuntime.GetPropertyValue(CurrentDevice.Id, nameof(ModbusSlaveVariableProperty.DataType));
|
||||
if (Enum.TryParse(type, out DataTypeEnum result))
|
||||
{
|
||||
await _plc.WriteAsync(item.Key, JToken.FromObject(item.Value.Value), result, cancellationToken).ConfigureAwait(false);
|
||||
await _plc.WriteAsync(item.Key, JToken.FromObject(variableRuntime.Value), result, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _plc.WriteAsync(item.Key, JToken.FromObject(item.Value.Value), item.Value.DataType, cancellationToken).ConfigureAwait(false);
|
||||
await _plc.WriteAsync(item.Key, JToken.FromObject(variableRuntime.Value), variableRuntime.DataType, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +255,7 @@ public class ModbusSlave : BusinessBase
|
||||
var address = variableRuntime.GetPropertyValue(DeviceId, nameof(_variablePropertys.ServiceAddress));
|
||||
if (address != null && variableRuntime.Value != null)
|
||||
{
|
||||
ModbusVariableQueue?.AddOrUpdate(address, address => variableRuntime, (address, addvalue) => variableRuntime);
|
||||
ModbusVariableQueue?.AddOrUpdate(address, address => variableRuntime.Id, (address, addvalue) => variableRuntime.Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Opc.Ua;
|
||||
@@ -95,12 +97,9 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
fs.EventNotifier = EventNotifiers.SubscribeToEvents;
|
||||
if (item?.Any() == true)
|
||||
{
|
||||
FolderState varFolder = CreateFolder(fs, "Variables", "Variables");
|
||||
varFolder.AddReference(ReferenceTypes.Organizes, true, ObjectIds.ObjectsFolder);
|
||||
varFolder.EventNotifier = EventNotifiers.SubscribeToEvents;
|
||||
foreach (var item2 in item)
|
||||
{
|
||||
CreateVariable(varFolder, item2);
|
||||
CreateVariable(fs, item2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,7 +228,7 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
/// 更新变量
|
||||
/// </summary>
|
||||
/// <param name="variable"></param>
|
||||
public void UpVariable(VariableRuntime variable)
|
||||
public void UpVariable(VariableBasicData variable)
|
||||
{
|
||||
if (!NodeIdTags.TryGetValue($"{variable.DeviceName}.{variable.Name}", out var uaTag))
|
||||
return;
|
||||
@@ -290,6 +289,8 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
return DataTypeIds.String;
|
||||
if (tp == typeof(DateTime))
|
||||
return DataTypeIds.DateTime;
|
||||
if (tp == typeof(decimal))
|
||||
return DataTypeIds.Decimal;
|
||||
return DataTypeIds.String;
|
||||
}
|
||||
|
||||
@@ -315,6 +316,14 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
jToken.CalculateActualValueRank(),
|
||||
jToken
|
||||
);
|
||||
if (dataValue == null)
|
||||
{
|
||||
_businessBase.LogMessage?.LogWarning($"{tag.NodeId} value is null , jToken: {jToken}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_businessBase.LogMessage?.LogTrace($"{tag.NodeId} value {dataValue} , jToken: {jToken}");
|
||||
}
|
||||
newValue = dataValue;
|
||||
success = true;
|
||||
}
|
||||
@@ -338,7 +347,6 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
else
|
||||
tag.ValueRank = ValueRanks.Scalar;
|
||||
|
||||
|
||||
var tp = elementType ?? value?.GetType() ?? typeof(string);
|
||||
|
||||
tag.DataType = DataNodeType(tp);
|
||||
@@ -395,78 +403,78 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
};
|
||||
|
||||
// 添加自定义属性
|
||||
{
|
||||
var property = new PropertyState<string>(folder)
|
||||
{
|
||||
NodeId = new NodeId($"{deviceRuntime.Name}.PluginName", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("PluginName", NamespaceIndex),
|
||||
DisplayName = "PluginName",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = deviceRuntime.PluginName ?? string.Empty
|
||||
};
|
||||
AddProperty(folder, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(folder)
|
||||
{
|
||||
NodeId = new NodeId($"{deviceRuntime.Name}.Remark1", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark1", NamespaceIndex),
|
||||
DisplayName = "Remark1",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = deviceRuntime.Remark1 ?? string.Empty
|
||||
};
|
||||
AddProperty(folder, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(folder)
|
||||
{
|
||||
NodeId = new NodeId($"{deviceRuntime.Name}.Remark2", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark2", NamespaceIndex),
|
||||
DisplayName = "Remark2",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = deviceRuntime.Remark2 ?? string.Empty
|
||||
};
|
||||
AddProperty(folder, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(folder)
|
||||
{
|
||||
NodeId = new NodeId($"{deviceRuntime.Name}.Remark3", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark3", NamespaceIndex),
|
||||
DisplayName = "Remark3",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = deviceRuntime.Remark3 ?? string.Empty
|
||||
};
|
||||
AddProperty(folder, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(folder)
|
||||
{
|
||||
NodeId = new NodeId($"{deviceRuntime.Name}.Remark4", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark4", NamespaceIndex),
|
||||
DisplayName = "Remark4",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = deviceRuntime.Remark4 ?? string.Empty
|
||||
};
|
||||
AddProperty(folder, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(folder)
|
||||
{
|
||||
NodeId = new NodeId($"{deviceRuntime.Name}.Remark5", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark5", NamespaceIndex),
|
||||
DisplayName = "Remark5",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = deviceRuntime.Remark5 ?? string.Empty
|
||||
};
|
||||
AddProperty(folder, property);
|
||||
}
|
||||
//{
|
||||
// var property = new PropertyState<string>(folder)
|
||||
// {
|
||||
// NodeId = new NodeId($"{deviceRuntime.Name}.PluginName", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("PluginName", NamespaceIndex),
|
||||
// DisplayName = "PluginName",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = deviceRuntime.PluginName ?? string.Empty
|
||||
// };
|
||||
// AddProperty(folder, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(folder)
|
||||
// {
|
||||
// NodeId = new NodeId($"{deviceRuntime.Name}.Remark1", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark1", NamespaceIndex),
|
||||
// DisplayName = "Remark1",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = deviceRuntime.Remark1 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(folder, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(folder)
|
||||
// {
|
||||
// NodeId = new NodeId($"{deviceRuntime.Name}.Remark2", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark2", NamespaceIndex),
|
||||
// DisplayName = "Remark2",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = deviceRuntime.Remark2 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(folder, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(folder)
|
||||
// {
|
||||
// NodeId = new NodeId($"{deviceRuntime.Name}.Remark3", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark3", NamespaceIndex),
|
||||
// DisplayName = "Remark3",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = deviceRuntime.Remark3 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(folder, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(folder)
|
||||
// {
|
||||
// NodeId = new NodeId($"{deviceRuntime.Name}.Remark4", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark4", NamespaceIndex),
|
||||
// DisplayName = "Remark4",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = deviceRuntime.Remark4 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(folder, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(folder)
|
||||
// {
|
||||
// NodeId = new NodeId($"{deviceRuntime.Name}.Remark5", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark5", NamespaceIndex),
|
||||
// DisplayName = "Remark5",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = deviceRuntime.Remark5 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(folder, property);
|
||||
//}
|
||||
|
||||
|
||||
parent?.AddChild(folder);
|
||||
@@ -494,8 +502,18 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
UserWriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Id = variableRuntime.Id,
|
||||
DataType = DataNodeType(variableRuntime),
|
||||
};
|
||||
var type = DataNodeType(variableRuntime);
|
||||
if (type != null)
|
||||
{
|
||||
variable.DataType = type;
|
||||
variable.IsDataTypeInit = true;
|
||||
var elementType = variableRuntime.Value?.GetType()?.GetElementTypeEx();
|
||||
if (elementType != null)
|
||||
variable.ValueRank = ValueRanks.OneOrMoreDimensions;
|
||||
else
|
||||
variable.ValueRank = ValueRanks.Scalar;
|
||||
}
|
||||
var service = dbDrivers.FirstOrDefault(a => GlobalData.ContainsVariable(a.DeviceId, variableRuntime));
|
||||
var level = ThingsGatewayNodeManager.ProtectTypeTrans(variableRuntime, service != null);
|
||||
variable.AccessLevel = level;
|
||||
@@ -507,101 +525,101 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
variable.StatusCode = code;
|
||||
variable.Timestamp = variableRuntime.CollectTime;
|
||||
variable.OnWriteValue = OnWriteDataValue;
|
||||
parent?.AddChild(variable);
|
||||
|
||||
// 添加自定义属性
|
||||
{
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Unit", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Unit", NamespaceIndex),
|
||||
DisplayName = "Unit",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.Unit ?? string.Empty
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
//// 添加自定义属性
|
||||
//{
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Unit", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Unit", NamespaceIndex),
|
||||
// DisplayName = "Unit",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.Unit ?? string.Empty
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
|
||||
}
|
||||
if (!variableRuntime.CollectGroup.IsNullOrEmpty())
|
||||
{
|
||||
//}
|
||||
//if (!variableRuntime.CollectGroup.IsNullOrEmpty())
|
||||
//{
|
||||
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.CollectGroup", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("CollectGroup", NamespaceIndex),
|
||||
DisplayName = "CollectGroup",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.CollectGroup,
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark1", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark1", NamespaceIndex),
|
||||
DisplayName = "Remark1",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.Remark1 ?? string.Empty
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
}
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.CollectGroup", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("CollectGroup", NamespaceIndex),
|
||||
// DisplayName = "CollectGroup",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.CollectGroup,
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark1", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark1", NamespaceIndex),
|
||||
// DisplayName = "Remark1",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.Remark1 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
//}
|
||||
|
||||
{
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark2", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark2", NamespaceIndex),
|
||||
DisplayName = "Remark2",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.Remark2 ?? string.Empty
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
}
|
||||
//{
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark2", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark2", NamespaceIndex),
|
||||
// DisplayName = "Remark2",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.Remark2 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
//}
|
||||
|
||||
{
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark3", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark3", NamespaceIndex),
|
||||
DisplayName = "Remark3",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.Remark3 ?? string.Empty
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
}
|
||||
//{
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark3", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark3", NamespaceIndex),
|
||||
// DisplayName = "Remark3",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.Remark3 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
//}
|
||||
|
||||
{
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark4", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark4", NamespaceIndex),
|
||||
DisplayName = "Remark4",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.Remark4 ?? string.Empty
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
}
|
||||
{
|
||||
var property = new PropertyState<string>(variable)
|
||||
{
|
||||
NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark5", NamespaceIndex),
|
||||
BrowseName = new QualifiedName("Remark5", NamespaceIndex),
|
||||
DisplayName = "Remark5",
|
||||
DataType = DataTypeIds.String,
|
||||
ValueRank = ValueRanks.Scalar,
|
||||
Value = variableRuntime.Remark5 ?? string.Empty
|
||||
};
|
||||
AddProperty(variable, property);
|
||||
}
|
||||
//{
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark4", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark4", NamespaceIndex),
|
||||
// DisplayName = "Remark4",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.Remark4 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
//}
|
||||
//{
|
||||
// var property = new PropertyState<string>(variable)
|
||||
// {
|
||||
// NodeId = new NodeId($"{variableRuntime.DeviceName}.{variableRuntime.Name}.Remark5", NamespaceIndex),
|
||||
// BrowseName = new QualifiedName("Remark5", NamespaceIndex),
|
||||
// DisplayName = "Remark5",
|
||||
// DataType = DataTypeIds.String,
|
||||
// ValueRank = ValueRanks.Scalar,
|
||||
// Value = variableRuntime.Remark5 ?? string.Empty
|
||||
// };
|
||||
// AddProperty(variable, property);
|
||||
//}
|
||||
|
||||
NodeIdTags.AddOrUpdate($"{variableRuntime.DeviceName}.{variableRuntime.Name}", variable);
|
||||
parent?.AddChild(variable);
|
||||
return variable;
|
||||
}
|
||||
|
||||
@@ -941,20 +959,24 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
|
||||
/// </summary>
|
||||
/// <param name="variableRuntime"></param>
|
||||
/// <returns></returns>
|
||||
private NodeId DataNodeType(VariableRuntime variableRuntime)
|
||||
private NodeId? DataNodeType(VariableRuntime variableRuntime)
|
||||
{
|
||||
var str = variableRuntime.GetPropertyValue(_businessBase.DeviceId, nameof(OpcUaServerVariableProperty.DataType)) ?? "";
|
||||
Type tp;
|
||||
if (Enum.TryParse(str, out DataTypeEnum result))
|
||||
{
|
||||
tp = result.GetSystemType();
|
||||
return DataNodeType(tp);
|
||||
}
|
||||
else
|
||||
{
|
||||
tp = variableRuntime.Value?.GetType() ?? variableRuntime.DataType.GetSystemType(); ;
|
||||
tp = variableRuntime.Value?.GetType();
|
||||
if (tp != null)
|
||||
{
|
||||
return DataNodeType(tp);
|
||||
}
|
||||
}
|
||||
|
||||
return DataNodeType(tp);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,9 +14,10 @@ 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;
|
||||
@@ -43,7 +44,7 @@ public partial class OpcUaServer : BusinessBase
|
||||
protected override BusinessPropertyBase _businessPropertyBase => _driverPropertys;
|
||||
|
||||
protected IStringLocalizer Localizer { get; private set; }
|
||||
private ConcurrentHashSet<long> CollectVariableRuntimes { get; set; } = new();
|
||||
private ConcurrentDictionary<long, VariableBasicData> CollectVariableRuntimes { get; set; } = new();
|
||||
|
||||
private static readonly string[] separator = new string[] { ";" };
|
||||
|
||||
@@ -53,9 +54,11 @@ public partial class OpcUaServer : BusinessBase
|
||||
//opcua类库内部有大量缓存,如果刷新变量次数大于一定数量,应该重启服务以防止OOM
|
||||
if (Interlocked.Increment(ref VariableChangedCount) > 100)
|
||||
{
|
||||
await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await DeviceThreadManage.RestartDeviceAsync(CurrentDevice, false).ConfigureAwait(false);
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
await DeviceThreadManage.RestartDeviceAsync(CurrentDevice, false).ConfigureAwait(false);
|
||||
}
|
||||
, cancellationToken);
|
||||
return;
|
||||
@@ -88,6 +91,19 @@ public partial class OpcUaServer : BusinessBase
|
||||
|
||||
|
||||
protected override async Task InitChannelAsync(IChannel? channel, CancellationToken cancellationToken)
|
||||
{
|
||||
await UaInit().ConfigureAwait(false);
|
||||
|
||||
GlobalData.VariableValueChangeEvent += VariableValueChange;
|
||||
|
||||
Localizer = App.CreateLocalizerByType(typeof(OpcUaServer))!;
|
||||
|
||||
await base.InitChannelAsync(channel, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private async Task UaInit()
|
||||
{
|
||||
ApplicationInstance.MessageDlg = new ApplicationMessageDlg(LogMessage);//默认返回true
|
||||
|
||||
@@ -105,17 +121,14 @@ public partial class OpcUaServer : BusinessBase
|
||||
}
|
||||
|
||||
m_server = new(this);
|
||||
|
||||
|
||||
GlobalData.VariableValueChangeEvent += VariableValueChange;
|
||||
|
||||
Localizer = App.CreateLocalizerByType(typeof(OpcUaServer))!;
|
||||
|
||||
await base.InitChannelAsync(channel, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void UaDispose()
|
||||
{
|
||||
ApplicationInstance.MessageDlg = null;
|
||||
m_server?.Stop();
|
||||
m_server?.NodeManager?.SafeDispose();
|
||||
m_server?.SafeDispose();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override bool IsConnected()
|
||||
{
|
||||
@@ -134,18 +147,24 @@ public partial class OpcUaServer : BusinessBase
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
GlobalData.VariableValueChangeEvent -= VariableValueChange;
|
||||
m_server?.Stop();
|
||||
m_server?.SafeDispose();
|
||||
UaDispose();
|
||||
CollectVariableRuntimes?.Clear();
|
||||
IdVariableRuntimes?.Clear();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override async Task ProtectedStartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// 启动服务器。
|
||||
await m_application.CheckApplicationInstanceCertificates(true, 1200, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await m_application.Start(m_server).ConfigureAwait(false);
|
||||
IdVariableRuntimes.ForEach(a =>
|
||||
{
|
||||
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
|
||||
});
|
||||
await base.ProtectedStartAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -157,10 +176,11 @@ public partial class OpcUaServer : BusinessBase
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(3000, cancellationToken).ConfigureAwait(false);
|
||||
await Task.Delay(2000, cancellationToken).ConfigureAwait(false);
|
||||
await m_application.CheckApplicationInstanceCertificates(true, 1200, cancellationToken).ConfigureAwait(false);
|
||||
await m_application.Start(m_server).ConfigureAwait(false);
|
||||
connect_success = true;
|
||||
await Task.Delay(2000, cancellationToken).ConfigureAwait(false);
|
||||
IdVariableRuntimes.ForEach(a =>
|
||||
{
|
||||
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
|
||||
@@ -174,17 +194,14 @@ public partial class OpcUaServer : BusinessBase
|
||||
await Task.Delay(10000, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
var varList = CollectVariableRuntimes.ToIEnumerableWithDequeue();
|
||||
var varList = CollectVariableRuntimes.ToListWithDequeue();
|
||||
foreach (var item in varList)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (IdVariableRuntimes.TryGetValue(item, out var variableRuntime) && variableRuntime != null)
|
||||
{
|
||||
m_server?.NodeManager?.UpVariable(variableRuntime);
|
||||
}
|
||||
m_server?.NodeManager?.UpVariable(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -397,12 +414,12 @@ public partial class OpcUaServer : BusinessBase
|
||||
}
|
||||
private void VariableValueChange(VariableRuntime variableRuntime, VariableBasicData variableData)
|
||||
{
|
||||
if (CurrentDevice.Pause)
|
||||
return;
|
||||
//if (CurrentDevice.Pause)
|
||||
// return;
|
||||
if (TaskSchedulerLoop?.Stoped == true) return;
|
||||
if (DisposedValue) return;
|
||||
if (IdVariableRuntimes.ContainsKey(variableData.Id))
|
||||
CollectVariableRuntimes.TryAdd(variableData.Id);
|
||||
CollectVariableRuntimes.AddOrUpdate(variableData.Id, variableData, (a, b) => variableData);
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Plugin.Synchronization" Version="$(ProPluginVersion)" GeneratePathProperty="true">
|
||||
<PackageReference Include="ThingsGateway.Plugin.SyncBridge" Version="$(ProPluginVersion)" GeneratePathProperty="true">
|
||||
<Private>false</Private>
|
||||
<IncludeAssets> native;</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -64,7 +64,7 @@
|
||||
<PkgThingsGateway_Plugin_SECSPackageFiles Include="$(PkgThingsGateway_Plugin_SECS)\Content\$(PluginTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_TS550PackageFiles Include="$(PkgThingsGateway_Plugin_TS550)\Content\$(PluginTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_VigorPackageFiles Include="$(PkgThingsGateway_Plugin_Vigor)\Content\$(PluginTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_SynchronizationPackageFiles Include="$(PkgThingsGateway_Plugin_Synchronization)\Content\$(PluginTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_SyncBridgePackageFiles Include="$(PkgThingsGateway_Plugin_SyncBridge)\Content\$(PluginTargetFramework)\**\*.*" />
|
||||
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
@@ -91,7 +91,7 @@
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_TS550PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.TS550%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_VigorPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Vigor%(RecursiveDir)" />
|
||||
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_VigorPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Synchronization%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_SyncBridgePackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.SyncBridge%(RecursiveDir)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.Synchronization\ThingsGateway.Plugin.Synchronization.csproj" />
|
||||
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.SyncBridge\ThingsGateway.Plugin.SyncBridge.csproj" />
|
||||
|
||||
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\ThingsGateway.Plugin.AllenBradleyCip.csproj" />
|
||||
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.BACnet\ThingsGateway.Plugin.BACnet.csproj" />
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.11" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.12" />
|
||||
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user