Compare commits

...

10 Commits

Author SHA1 Message Date
2248356998 qq.com
4a7534b210 添加 脚本调试项目 2025-09-22 10:36:28 +08:00
2248356998 qq.com
58e099cb93 10.11.58 2025-09-21 20:53:50 +08:00
2248356998 qq.com
a94a9c953c 10.11.57 2025-09-19 14:32:34 +08:00
Diego
35e1ffa3e9 添加文件 2025-09-18 17:54:29 +08:00
Diego
4921642151 10.11.56 2025-09-18 17:15:57 +08:00
2248356998 qq.com
d71ee29da8 10.11.54 2025-09-17 20:50:41 +08:00
2248356998 qq.com
901aa2d59f 10.11.52 2025-09-17 11:07:45 +08:00
2248356998 qq.com
764957c014 10.11.51 2025-09-16 22:19:01 +08:00
Diego
0e3898218b 10.11.44 2025-09-16 19:13:19 +08:00
Diego
61f13cef3c 10.11.43 2025-09-15 17:35:49 +08:00
109 changed files with 2153 additions and 300 deletions

View File

@@ -15,7 +15,7 @@
</Card>
</div>
<div class="col-12 col-sm-10 h-100">
<div class="col-12 col-sm-10 h-100 ps-2">
<AdminTable @ref=table TItem="SysUser"
AutoGenerateColumns="true"
ShowAdvancedSearch=false

View File

@@ -26,6 +26,8 @@
<link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/motronic.min.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"ThingsGateway.AdminServer.styles.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/site.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/devui.css?v={this.GetType().Assembly.GetName().Version}") />
@* <script src=@($"{WebsiteConst.DefaultResourceUrl}js/theme.js") type="module"></script><!-- 初始主题 --> *@
<!-- PWA Manifest -->
<link rel="manifest" href="./manifest.json" />
@@ -44,6 +46,7 @@
<!-- PWA Service Worker -->
<script type="text/javascript">'serviceWorker' in navigator && navigator.serviceWorker.register('./service-worker.js')</script>
<script src="pwa-install.js"></script>
</body>
</html>

View File

@@ -0,0 +1,34 @@
let installPromptTriggered = false;
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? match[2] : null;
}
function hasShownInstallPrompt() {
return getCookie("tgPWAInstallPromptShown") === "true";
}
function markInstallPromptShown() {
document.cookie = "tgPWAInstallPromptShown=true; max-age=31536000; path=/";
}
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
if (!hasShownInstallPrompt() && !installPromptTriggered) {
installPromptTriggered = true;
setTimeout(() => {
e.prompt()
.then(() => e.userChoice)
.then(choiceResult => {
markInstallPromptShown();
})
.catch(err => {
// 可选错误处理
});
}, 2000); // 延迟 2 秒提示
} else {
// console.log("已提示过安装,不再弹出");
}
});

View File

@@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.6" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
<PackageReference Include="BootstrapBlazor" Version="9.10.1" />
<PackageReference Include="BootstrapBlazor" Version="9.10.2" />
</ItemGroup>
<ItemGroup>

View File

@@ -15,23 +15,19 @@ public class ExpiringDictionary<TKey, TValue> : IDisposable
public void TryAdd(TKey key, TValue value)
{
if (_cleanupTimer.Disposed) throw new ObjectDisposedException(nameof(ExpiringDictionary<TKey, TValue>));
_dict.TryAdd(key, value);
}
public bool TryGetValue(TKey key, out TValue value)
{
if (_cleanupTimer.Disposed) throw new ObjectDisposedException(nameof(ExpiringDictionary<TKey, TValue>));
return _dict.TryGetValue(key, out value);
}
public TValue GetOrAdd(TKey key, Func<TKey, TValue> func)
{
if (_cleanupTimer.Disposed) throw new ObjectDisposedException(nameof(ExpiringDictionary<TKey, TValue>));
return _dict.GetOrAdd(key, func);
}
public TValue GetOrAdd(TKey key, TValue value)
{
if (_cleanupTimer.Disposed) throw new ObjectDisposedException(nameof(ExpiringDictionary<TKey, TValue>));
return _dict.GetOrAdd(key, value);
}

View File

@@ -106,6 +106,17 @@ public static class Runtime
#if NET6_0_OR_GREATER
public static Boolean IsSystemd
{
get
{
var id = Environment.GetEnvironmentVariable("INVOCATION_ID");
return !string.IsNullOrEmpty(id);
}
}
public static Boolean? isLegacyWindows;
/// <summary>

View File

@@ -10,7 +10,7 @@
using Newtonsoft.Json.Linq;
namespace ThingsGateway.Foundation;
namespace ThingsGateway.NewLife.Json.Extension;
/// <summary>
/// JTokenUtil
@@ -131,6 +131,63 @@ public static class JTokenUtil
}
}
/// <summary>
/// 把任意对象转换为 JToken。
/// 支持 JsonElement、JToken、本地 CLR 类型。
/// </summary>
public static JToken GetJTokenFromObj(this object value)
{
if (value == null)
return JValue.CreateNull();
switch (value)
{
case JToken jt:
return jt;
#if NET6_0_OR_GREATER
case System.Text.Json.JsonElement elem:
return elem.ToJToken();
#endif
case string s:
return new JValue(s);
case bool b:
return new JValue(b);
case int i:
return new JValue(i);
case long l:
return new JValue(l);
case double d:
return new JValue(d);
case float f:
return new JValue(f);
case decimal m:
return new JValue(m);
case DateTime dt:
return new JValue(dt);
case DateTimeOffset dto:
return new JValue(dto);
case Guid g:
return new JValue(g);
default:
// 兜底:用 Newtonsoft 来包装成 JToken
return JToken.FromObject(value);
}
}
#region json
/// <summary>

View File

@@ -0,0 +1,176 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
#if NET6_0_OR_GREATER
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Globalization;
using System.Numerics;
using System.Text.Json;
namespace ThingsGateway.NewLife.Json.Extension;
public static class JsonElementExtensions
{
public static string GetValue(object src, bool parseBoolNumber = false)
{
if (src == null)
return string.Empty;
switch (src)
{
case string strValue:
return strValue;
case bool boolValue:
return boolValue ? parseBoolNumber ? "1" : "True" : parseBoolNumber ? "0" : "False";
case JsonElement elem: // System.Text.Json.JsonElement
return elem.ValueKind switch
{
JsonValueKind.String => elem.GetString(),
JsonValueKind.Number => elem.GetRawText(), // 或 elem.GetDecimal().ToString()
JsonValueKind.True => "1",
JsonValueKind.False => "0",
JsonValueKind.Null => string.Empty,
_ => elem.GetRawText(), // 对象、数组等直接输出 JSON
};
default:
return (src).GetJTokenFromObj().ToString();
}
}
/// <summary>
/// 将 System.Text.Json.JsonElement 递归转换为 Newtonsoft.Json.Linq.JToken
/// - tryParseDates: 是否尝试把字符串解析为 DateTime/DateTimeOffset
/// - tryParseGuids: 是否尝试把字符串解析为 Guid
/// </summary>
public static JToken ToJToken(this JsonElement element, bool tryParseDates = true, bool tryParseGuids = true)
{
switch (element.ValueKind)
{
case JsonValueKind.Object:
var obj = new JObject();
foreach (var prop in element.EnumerateObject())
obj.Add(prop.Name, prop.Value.ToJToken(tryParseDates, tryParseGuids));
return obj;
case JsonValueKind.Array:
var arr = new JArray();
foreach (var item in element.EnumerateArray())
arr.Add(item.ToJToken(tryParseDates, tryParseGuids));
return arr;
case JsonValueKind.String:
// 优先按语义尝试解析 Guid / DateTimeOffset / DateTime
if (tryParseGuids && element.TryGetGuid(out Guid g))
return new JValue(g);
if (tryParseDates && element.TryGetDateTimeOffset(out DateTimeOffset dto))
return new JValue(dto);
if (tryParseDates && element.TryGetDateTime(out DateTime dt))
return new JValue(dt);
return new JValue(element.GetString());
case JsonValueKind.Number:
return NumberElementToJToken(element);
case JsonValueKind.True:
return new JValue(true);
case JsonValueKind.False:
return new JValue(false);
case JsonValueKind.Null:
case JsonValueKind.Undefined:
default:
return JValue.CreateNull();
}
}
private static JToken NumberElementToJToken(JsonElement element)
{
// 取原始文本(保持原始表示,方便处理超出标准类型范围的数字)
string raw = element.GetRawText(); // 例如 "123", "1.23e4"
// 如果不含小数点或指数优先尝试整数解析long / ulong / BigInteger
if (!raw.Contains('.') && !raw.Contains('e') && !raw.Contains('E'))
{
if (long.TryParse(raw, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var l))
return new JValue(l);
if (ulong.TryParse(raw, NumberStyles.None, CultureInfo.InvariantCulture, out var ul))
return new JValue(ul);
if (BigInteger.TryParse(raw, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var bi))
// BigInteger 可能不被 JValue 直接识别为数字类型,使用 FromObject 保证正确表示
return JToken.FromObject(bi);
}
// 含小数或指数,或整数解析失败,尝试 decimal -> double
if (decimal.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var dec))
return new JValue(dec);
if (double.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var d))
return new JValue(d);
// 最后兜底:把原始文本当字符串返回(极端情况)
return new JValue(raw);
}
/// <summary>
/// 把 JToken 转成“平面”字符串,适合用于日志或写入 CSV 的单元格:
/// - string -> 原文
/// - bool -> "1"/"0"
/// - number -> 原始数字文本
/// - date -> ISO 8601 (o)
/// - object/array -> 紧凑的 JSON 文本
/// - null/undefined -> empty string
/// </summary>
public static string JTokenToPlainString(this JToken token)
{
if (token == null || token.Type == JTokenType.Null || token.Type == JTokenType.Undefined)
return string.Empty;
switch (token.Type)
{
case JTokenType.String:
return token.Value<string>() ?? string.Empty;
case JTokenType.Boolean:
return token.Value<bool>() ? "1" : "0";
case JTokenType.Integer:
case JTokenType.Float:
// 保持紧凑数字文本(不加引号)
return token.ToString(Formatting.None);
case JTokenType.Date:
{
// Date 类型可能是 DateTime 或 DateTimeOffset
var val = token.Value<object>();
if (val is DateTimeOffset dto) return dto.ToString("o");
if (val is DateTime dt) return dt.ToString("o");
return token.ToString(Formatting.None);
}
default:
// 对象/数组等,返回紧凑 JSON 表示
return token.ToString(Formatting.None);
}
}
}
#endif

View File

@@ -21,6 +21,7 @@ public class Setting : Config<Setting>
#region
/// <summary>是否启用全局调试。默认启用</summary>
[Description("全局调试。XTrace.Debug")]
[XmlIgnore, IgnoreDataMember]
public Boolean Debug { get; set; } = true;
/// <summary>日志等级只输出大于等于该级别的日志All/Debug/Info/Warn/Error/Fatal默认Info</summary>
@@ -30,6 +31,7 @@ public class Setting : Config<Setting>
/// <summary>文件日志目录。默认Log子目录</summary>
[Description("文件日志目录。默认Log子目录")]
[XmlIgnore, IgnoreDataMember]
public String LogPath { get; set; } = "Logs/XLog";
/// <summary>日志文件上限。超过上限后拆分新日志文件默认5MB0表示不限制大小</summary>
@@ -42,6 +44,7 @@ public class Setting : Config<Setting>
/// <summary>日志文件格式。默认{0:yyyy_MM_dd}.log支持日志等级如 {1}_{0:yyyy_MM_dd}.log</summary>
[Description("日志文件格式。默认{0:yyyy_MM_dd}.log支持日志等级如 {1}_{0:yyyy_MM_dd}.log")]
[XmlIgnore, IgnoreDataMember]
public String LogFileFormat { get; set; } = "{0:yyyy_MM_dd}.log";
/// <summary>日志行格式。默认Time|ThreadId|Kind|Name|Message还支持Level</summary>

View File

@@ -52,7 +52,7 @@
<ItemGroup>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

View File

@@ -1,11 +1,11 @@
<Project>
<PropertyGroup>
<PluginVersion>10.11.42</PluginVersion>
<ProPluginVersion>10.11.42</ProPluginVersion>
<DefaultVersion>10.11.42</DefaultVersion>
<AuthenticationVersion>10.11.5</AuthenticationVersion>
<SourceGeneratorVersion>10.11.4</SourceGeneratorVersion>
<PluginVersion>10.11.62</PluginVersion>
<ProPluginVersion>10.11.62</ProPluginVersion>
<DefaultVersion>10.11.62</DefaultVersion>
<AuthenticationVersion>10.11.6</AuthenticationVersion>
<SourceGeneratorVersion>10.11.6</SourceGeneratorVersion>
<NET8Version>8.0.20</NET8Version>
<NET9Version>9.0.9</NET9Version>
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>

View File

@@ -136,6 +136,9 @@ public static class CSharpScriptEngineExtension
}
catch (NullReferenceException)
{
//如果编译失败应该不重复编译避免oom
Instance.Set<T>(field, null, TimeSpan.FromHours(1));
string exString = string.Format(CSScriptResource.CSScriptResource.Error1, typeof(T).FullName);
throw new(exString);
}

View File

@@ -68,6 +68,7 @@ public class ModbusMasterDemo
bytes = await device.ModbusReadAsync(new ModbusAddress()
{
Station = 1,
StartAddress = 0,
FunctionCode = 3,
Length = 10,
@@ -92,6 +93,7 @@ public class ModbusMasterDemo
write = await device.ModbusRequestAsync(new ModbusAddress()
{
Station = 1,
StartAddress = 0,
FunctionCode = 3,
MasterWriteDatas = device.ThingsGatewayBitConverter.GetBytes(new double[] { 123.456, 123.456 })

View File

@@ -14,6 +14,7 @@ using Newtonsoft.Json.Linq;
using System.Linq.Expressions;
using ThingsGateway.Gateway.Application.Extensions;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.NewLife.Reflection;
namespace ThingsGateway.Foundation;
@@ -68,12 +69,12 @@ public abstract class VariableObject
/// <returns></returns>
public virtual JToken GetExpressionsValue(object value, VariableRuntimeProperty variableRuntimeProperty)
{
var jToken = JToken.FromObject(value);
var jToken = value.GetJTokenFromObj();
if (!string.IsNullOrEmpty(variableRuntimeProperty.Attribute.WriteExpressions))
{
object rawdata = jToken.GetObjectFromJToken();
object data = variableRuntimeProperty.Attribute.WriteExpressions.GetExpressionsResult(rawdata, Device?.Logger);
jToken = JToken.FromObject(data);
jToken = data.GetJTokenFromObj();
}
return jToken;

View File

@@ -98,6 +98,19 @@ public static class ChannelOptionsExtensions
if (channelOptions.MaxClientCount > 0)
config.SetMaxCount(channelOptions.MaxClientCount);
config.SetTransportOption(new TouchSocket.Sockets.TransportOption()
{
SendPipeOptions = new System.IO.Pipelines.PipeOptions(
minimumSegmentSize: 1024,
useSynchronizationContext: false),
ReceivePipeOptions = new System.IO.Pipelines.PipeOptions(
minimumSegmentSize: 1024,
pauseWriterThreshold: 1024 * 1024,
resumeWriterThreshold: 1024 * 512,
useSynchronizationContext: false)
});
switch (channelType)
{
case ChannelTypeEnum.TcpClient:
@@ -125,7 +138,7 @@ public static class ChannelOptionsExtensions
/// <param name="config">配置</param>
/// <param name="channelOptions">串口配置</param>
/// <returns></returns>
public static SerialPortChannel GetSerialPort(this TouchSocketConfig config, IChannelOptions channelOptions)
private static SerialPortChannel GetSerialPort(this TouchSocketConfig config, IChannelOptions channelOptions)
{
var serialPortOption = channelOptions.Map<SerialPortOption>();
serialPortOption.ThrowIfNull(nameof(SerialPortOption));
@@ -143,7 +156,7 @@ public static class ChannelOptionsExtensions
/// <param name="channelOptions">通道配置</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static TcpClientChannel GetTcpClient(this TouchSocketConfig config, IChannelOptions channelOptions)
private static TcpClientChannel GetTcpClient(this TouchSocketConfig config, IChannelOptions channelOptions)
{
var remoteUrl = channelOptions.RemoteUrl;
var bindUrl = channelOptions.BindUrl;
@@ -165,7 +178,7 @@ public static class ChannelOptionsExtensions
/// <param name="channelOptions">通道配置</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static IChannel GetTcpService(this TouchSocketConfig config, IChannelOptions channelOptions)
private static IChannel GetTcpService(this TouchSocketConfig config, IChannelOptions channelOptions)
{
var bindUrl = channelOptions.BindUrl;
bindUrl.ThrowIfNull(nameof(bindUrl));
@@ -193,7 +206,7 @@ public static class ChannelOptionsExtensions
/// <param name="channelOptions">通道配置</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static UdpSessionChannel GetUdpSession(this TouchSocketConfig config, IChannelOptions channelOptions)
private static UdpSessionChannel GetUdpSession(this TouchSocketConfig config, IChannelOptions channelOptions)
{
var remoteUrl = channelOptions.RemoteUrl;
var bindUrl = channelOptions.BindUrl;

View File

@@ -57,7 +57,7 @@ public interface IChannel : ISetupConfigObject, IDisposable, IClosableClient, IC
/// </summary>
public ChannelEventHandler Stoping { get; }
void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue);
void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1);
}

View File

@@ -30,6 +30,7 @@ public interface IClientChannel : IChannel, ISender, IClient, IClientSender, IOn
WaitHandlePool<MessageBase> WaitHandlePool { get; }
WaitLock GetLock(string key);
void LogSeted(bool logSeted);
/// <summary>
/// 设置数据处理适配器

View File

@@ -36,7 +36,7 @@ public class OtherChannel : SetupConfigObject, IClientChannel
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
public void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1)
{
var pool = WaitHandlePool;
WaitHandlePool = new WaitHandlePool<MessageBase>(minSign, maxSign);
@@ -68,7 +68,7 @@ public class OtherChannel : SetupConfigObject, IClientChannel
/// <summary>
/// 等待池
/// </summary>
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(0, ushort.MaxValue);
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(1, ushort.MaxValue - 1);
/// <inheritdoc/>
public WaitLock WaitLock => ChannelOptions.WaitLock;
@@ -98,7 +98,10 @@ public class OtherChannel : SetupConfigObject, IClientChannel
logSet = false;
}
public void LogSeted(bool logSeted)
{
logSet = logSeted;
}
/// <summary>
/// 设置数据处理适配器。
/// </summary>

View File

@@ -31,7 +31,7 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
public void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1)
{
var pool = WaitHandlePool;
WaitHandlePool = new WaitHandlePool<MessageBase>(minSign, maxSign);
@@ -71,6 +71,11 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
logSet = false;
}
public void LogSeted(bool logSeted)
{
logSet = logSeted;
}
/// <inheritdoc/>
public ChannelEventHandler Started { get; } = new();
@@ -86,7 +91,7 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
/// <summary>
/// 等待池
/// </summary>
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(0, ushort.MaxValue);
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(1, ushort.MaxValue - 1);
/// <inheritdoc/>
public WaitLock WaitLock => ChannelOptions.WaitLock;

View File

@@ -28,7 +28,7 @@ public class TcpClientChannel : TcpClient, IClientChannel
ResetSign();
}
public override TouchSocketConfig Config => base.Config ?? ChannelOptions.Config;
public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
public void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1)
{
var pool = WaitHandlePool;
WaitHandlePool = new WaitHandlePool<MessageBase>(minSign, maxSign);
@@ -51,6 +51,10 @@ public class TcpClientChannel : TcpClient, IClientChannel
logSet = false;
}
public void LogSeted(bool logSeted)
{
logSet = logSeted;
}
/// <inheritdoc/>
public ChannelReceivedEventHandler ChannelReceived { get; } = new();
@@ -79,7 +83,7 @@ public class TcpClientChannel : TcpClient, IClientChannel
/// <summary>
/// 等待池
/// </summary>
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(0, ushort.MaxValue);
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(1, ushort.MaxValue - 1);
public virtual WaitLock GetLock(string key) => WaitLock;
/// <inheritdoc/>

View File

@@ -210,7 +210,7 @@ public class TcpServiceChannel<TClient> : TcpServiceChannelBase<TClient>, IChann
}
public int MinSign { get; private set; } = 0;
public int MaxSign { get; private set; } = ushort.MaxValue;
public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
public void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1)
{
MinSign = minSign;
MaxSign = maxSign;

View File

@@ -43,8 +43,11 @@ public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
logSet = false;
}
public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
public void LogSeted(bool logSeted)
{
logSet = logSeted;
}
public void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1)
{
var pool = WaitHandlePool;
WaitHandlePool = new WaitHandlePool<MessageBase>(minSign, maxSign);
@@ -79,7 +82,7 @@ public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
/// <summary>
/// 等待池
/// </summary>
public WaitHandlePool<MessageBase> WaitHandlePool { get; private set; } = new(0, ushort.MaxValue);
public WaitHandlePool<MessageBase> WaitHandlePool { get; private set; } = new(1, ushort.MaxValue - 1);
/// <inheritdoc/>
public WaitLock WaitLock { get; internal set; } = new(nameof(TcpSessionClientChannel));

View File

@@ -40,6 +40,10 @@ public class UdpSessionChannel : UdpSession, IClientChannel
handleAdapter.Logger = log;
}
}
public void LogSeted(bool logSeted)
{
logSet = logSeted;
}
/// <inheritdoc/>
public void SetDataHandlingAdapter(DataHandlingAdapter adapter)
{
@@ -50,7 +54,7 @@ public class UdpSessionChannel : UdpSession, IClientChannel
}
public void ResetSign(int minSign = 0, int maxSign = ushort.MaxValue)
public void ResetSign(int minSign = 1, int maxSign = ushort.MaxValue - 1)
{
var pool = WaitHandlePool;
WaitHandlePool = new WaitHandlePool<MessageBase>(minSign, maxSign);
@@ -89,7 +93,7 @@ public class UdpSessionChannel : UdpSession, IClientChannel
/// <summary>
/// 等待池
/// </summary>
public WaitHandlePool<MessageBase> WaitHandlePool { get; set; } = new(0, ushort.MaxValue);
public WaitHandlePool<MessageBase> WaitHandlePool { get; internal set; } = new(1, ushort.MaxValue - 1);
/// <inheritdoc/>
public WaitLock WaitLock => ChannelOptions.WaitLock;

View File

@@ -569,7 +569,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
{
timeoutStatus = reusableTimeout.TimeoutStatus;
return timeoutStatus
? new MessageBase(new TimeoutException())
? new MessageBase(new TimeoutException()) { ErrorMessage = $"Timeout, sign: {sign}" }
: new MessageBase(new OperationCanceledException());
}
catch (Exception ex)
@@ -583,9 +583,15 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
_reusableTimeouts.Return(reusableTimeout);
}
return waitData.Status == WaitDataStatus.Success
? waitData.CompletedData
: new MessageBase(waitData.Check(timeoutStatus));
if (waitData.Status == WaitDataStatus.Success)
{
return waitData.CompletedData;
}
else
{
var operResult = waitData.Check(timeoutStatus);
return new MessageBase(operResult) { ErrorMessage = $"{operResult.ErrorMessage}, sign: {sign}" };
}
}
catch (Exception ex)
{
@@ -978,6 +984,7 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
{
lock (Channel)
{
Channel.Starting.Remove(ChannelStarting);
Channel.Stoped.Remove(ChannelStoped);
Channel.Started.Remove(ChannelStarted);
@@ -1018,6 +1025,11 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
}
Channel.Collects.Remove(this);
if (Channel is IClientChannel clientChannel)
{
clientChannel.LogSeted(false);
}
}
}
_reusableTimeouts?.SafeDispose();
@@ -1070,6 +1082,12 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice
}
Channel.Collects.Remove(this);
if (Channel is IClientChannel clientChannel)
{
clientChannel.LogSeted(false);
}
}
_reusableTimeouts?.SafeDispose();

View File

@@ -12,6 +12,7 @@ using System.Globalization;
using System.Net;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Foundation.Extension.String;

View File

@@ -11,8 +11,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="$(NET9Version)" />
<PackageReference Include="TouchSocket" Version="4.0.0-beta.27" />
<PackageReference Include="TouchSocket.SerialPorts" Version="4.0.0-beta.27" />
<PackageReference Include="TouchSocket" Version="4.0.0-beta.57" />
<PackageReference Include="TouchSocket.SerialPorts" Version="4.0.0-beta.57" />
</ItemGroup>
<ItemGroup>

View File

@@ -106,5 +106,5 @@ public class BusinessPropertyWithCacheIntervalScript : BusinessPropertyWithCache
/// </summary>
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public string? BigTextScriptPluginEventDataModel { get; set; }
public virtual string? BigTextScriptPluginEventDataModel { get; set; }
}

View File

@@ -482,7 +482,6 @@ public abstract partial class CollectBase : DriverBase
protected virtual Task TestOnline(object? state, CancellationToken cancellationToken)
{
CurrentDevice.SetDeviceStatus(TimerX.Now, false, null);
return Task.CompletedTask;
}
@@ -595,7 +594,7 @@ public abstract partial class CollectBase : DriverBase
// 根据写入表达式转换数据
object data = deviceVariable.WriteExpressions.GetExpressionsResult(rawdata, LogMessage);
// 将转换后的数据重新赋值给写入信息列表
writeInfoLists[deviceVariable] = JToken.FromObject(data);
writeInfoLists[deviceVariable] = JTokenUtil.GetJTokenFromObj(data);
}
catch (Exception ex)
{
@@ -663,7 +662,7 @@ public abstract partial class CollectBase : DriverBase
// 根据写入表达式转换数据
object data = deviceVariable.WriteExpressions.GetExpressionsResult(rawdata, LogMessage);
// 将转换后的数据重新赋值给写入信息列表
writeInfoLists[deviceVariable] = JToken.FromObject(data);
writeInfoLists[deviceVariable] = JTokenUtil.GetJTokenFromObj(data);
}
catch (Exception ex)
{

View File

@@ -1,53 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
namespace ThingsGateway.Gateway.Application;
/// <summary>
/// 插件配置项
/// <br></br>
/// 使用<see cref="DynamicPropertyAttribute"/> 标识所需的配置属性
/// </summary>
public class MempryDevicePropertyBase : CollectPropertyBase
{
}
/// <summary>
/// <para></para>
/// 采集插件继承实现不同PLC通讯
/// <para></para>
/// </summary>
public class MempryDevice : CollectBase
{
private MempryDevicePropertyBase _driverPropertyBase = new MempryDevicePropertyBase();
public override CollectPropertyBase CollectProperties => _driverPropertyBase;
#if !Management
/// <summary>
/// 是否连接成功
/// </summary>
public override bool IsConnected()
{
return true;
}
protected override Task<List<VariableSourceRead>> ProtectedLoadSourceReadAsync(List<VariableRuntime> deviceVariables)
{
return Task.FromResult(new List<VariableSourceRead>());
}
protected override bool IsRuntimeSourceValid(VariableRuntime a)
{
return false;
}
#endif
}

View File

@@ -37,6 +37,8 @@ public abstract class DriverBase : AsyncDisposableObject, IDriver
#region
public virtual bool RefreshRuntimeAlways { get; set; } = false;
/// <summary>
/// 调试UI Type如果不存在返回null
/// </summary>

View File

@@ -64,26 +64,36 @@ public static class DynamicModelExtension
if (GlobalData.IdDevices.TryGetValue(businessId, out var deviceRuntime))
{
if (deviceRuntime.Driver is BusinessBase businessBase && businessBase.DriverProperties is IBusinessPropertyAllVariableBase property)
if (deviceRuntime.Driver is BusinessBase businessBase)
{
if (property.IsAllVariable)
if (businessBase.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable)
{
// 检查是否存在对应的业务设备Id
if (variableRuntime.VariablePropertys?.ContainsKey(businessId) == true)
{
variableRuntime.VariablePropertys[businessId].TryGetValue(propertyName, out var value);
return value; // 返回属性值
}
else
{
return ThingsGatewayStringConverter.Default.Serialize(null, businessBase.VariablePropertys.GetValue(propertyName, false));
}
return GetVariableProperty(variableRuntime, businessId, propertyName, businessBase);
}
else if (businessBase.RefreshRuntimeAlways)
{
return GetVariableProperty(variableRuntime, businessId, propertyName, businessBase);
}
}
}
return null; // 未找到对应的业务设备Id返回null
static string? GetVariableProperty(VariableRuntime variableRuntime, long businessId, string propertyName, BusinessBase businessBase)
{
// 检查是否存在对应的业务设备Id
if (variableRuntime.VariablePropertys?.ContainsKey(businessId) == true)
{
variableRuntime.VariablePropertys[businessId].TryGetValue(propertyName, out var value);
return value; // 返回属性值
}
else
{
return ThingsGatewayStringConverter.Default.Serialize(null, businessBase.VariablePropertys.GetValue(propertyName, false));
}
}
}
#endif

View File

@@ -43,6 +43,7 @@ namespace ThingsGateway.Gateway.Application
string PluginDirectory { get; }
Dictionary<long, VariableRuntime> IdVariableRuntimes { get; }
IDeviceThreadManage DeviceThreadManage { get; }
bool RefreshRuntimeAlways { get; set; }
bool IsConnected();
void PauseThread(bool pause);

View File

@@ -15,6 +15,8 @@ using Riok.Mapperly.Abstractions;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Gateway.Application;
/// <summary>

View File

@@ -125,9 +125,14 @@ public static class GlobalData
{
if (GlobalData.IdDevices.TryGetValue(businessDeviceId, out var deviceRuntime))
{
if (deviceRuntime.Driver?.DriverProperties is IBusinessPropertyAllVariableBase property)
if (deviceRuntime.Driver is BusinessBase businessBase)
{
if (property.IsAllVariable)
if (businessBase.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable)
{
return true;
}
else if (businessBase.RefreshRuntimeAlways)
{
return true;
}
@@ -141,7 +146,46 @@ public static class GlobalData
return a.VariablePropertys?.ContainsKey(businessDeviceId) == true;
}
public static DeviceRuntime[] GetAllVariableBusinessDeviceRuntime()
{
var channelDevice = GlobalData.IdDevices.Where(a =>
{
if (a.Value.Driver is BusinessBase businessBase)
{
if (businessBase.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable)
{
return true;
}
else if (businessBase.RefreshRuntimeAlways)
{
return true;
}
}
return false;
}).Select(a => a.Value).ToArray();
return channelDevice;
}
public static IDriver[] GetAllVariableBusinessDriver()
{
var channelDevice = GlobalData.IdDevices.Where(a =>
{
if (a.Value.Driver is BusinessBase businessBase)
{
if (businessBase.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable)
{
return true;
}
else if (businessBase.RefreshRuntimeAlways)
{
return true;
}
}
return false;
}).Select(a => a.Value.Driver).ToArray();
return channelDevice;
}
/// <summary>
/// 只读的通道字典,提供对通道的只读访问
/// </summary>

View File

@@ -92,7 +92,7 @@ public partial class ManagementTask : AsyncDisposableObject
var tcpDmtpClient = new TcpDmtpClient();
var config = new TouchSocketConfig()
.SetRemoteIPHost(_managementOptions.ServerUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 1024 * 1024 * 1024 })
.SetAdapterOption(a => a.MaxPackageSize = 1024 * 1024 * 1024)
.SetDmtpOption(a => a.VerifyToken = _managementOptions.VerifyToken)
.ConfigureContainer(a =>
{
@@ -156,7 +156,7 @@ public partial class ManagementTask : AsyncDisposableObject
var tcpDmtpService = new TcpDmtpService();
var config = new TouchSocketConfig()
.SetListenIPHosts(_managementOptions.ServerUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 1024 * 1024 * 1024 })
.SetAdapterOption(a => a.MaxPackageSize = 1024 * 1024 * 1024)
.SetDmtpOption(a => a.VerifyToken = _managementOptions.VerifyToken)
.ConfigureContainer(a =>
{

View File

@@ -331,7 +331,7 @@ internal sealed class RedundancyTask : IRpcDriver, IAsyncDisposable
var tcpDmtpClient = new TcpDmtpClient();
var config = new TouchSocketConfig()
.SetRemoteIPHost(redundancy.MasterUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 0x20000000 })
.SetAdapterOption(a => a.MaxPackageSize = 0x20000000)
.SetDmtpOption(a => a.VerifyToken = redundancy.VerifyToken)
.ConfigureContainer(a =>
{
@@ -376,7 +376,7 @@ internal sealed class RedundancyTask : IRpcDriver, IAsyncDisposable
var tcpDmtpService = new TcpDmtpService();
var config = new TouchSocketConfig()
.SetListenIPHosts(redundancy.MasterUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 0x20000000 })
.SetAdapterOption(a => a.MaxPackageSize = 0x20000000)
.SetDmtpOption(a => a.VerifyToken = redundancy.VerifyToken)
.ConfigureContainer(a =>
{

View File

@@ -18,6 +18,7 @@ using ThingsGateway.Blazor.Diagrams.Core;
using ThingsGateway.Blazor.Diagrams.Core.Anchors;
using ThingsGateway.Blazor.Diagrams.Core.Geometry;
using ThingsGateway.Blazor.Diagrams.Core.Models;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Gateway.Application;
@@ -88,7 +89,7 @@ public static class RuleHelpers
var propertyInfos = nodeModel.GetType().GetRuntimeProperties().Where(a => a.GetCustomAttribute<ModelValue>() != null);
foreach (var item in propertyInfos)
{
jtokens.Add(item.Name, JToken.FromObject(item.GetValue(nodeModel) ?? JValue.CreateNull()));
jtokens.Add(item.Name, (item.GetValue(nodeModel) ?? JValue.CreateNull()).GetJTokenFromObj());
}
return jtokens;
}

View File

@@ -1,5 +1,7 @@
using Newtonsoft.Json.Linq;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Gateway.Application;
public class NodeInput
@@ -9,7 +11,7 @@ public class NodeInput
{
get
{
return JToken.FromObject(input);
return (input).GetJTokenFromObj();
}
}

View File

@@ -1,5 +1,7 @@
using Newtonsoft.Json.Linq;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Gateway.Application;
public class NodeOutput
@@ -9,7 +11,7 @@ public class NodeOutput
{
get
{
return JToken.FromObject(output);
return (output).GetJTokenFromObj();
}
}

View File

@@ -240,6 +240,11 @@ internal static class RuntimeServiceHelper
if (group.Key != null)
await group.Key.RestartDeviceAsync(group.Value, false).ConfigureAwait(false);
}
foreach (var group in GlobalData.GetAllVariableBusinessDeviceRuntime().Where(a => a.Driver?.DeviceThreadManage != null).GroupBy(a => a.Driver.DeviceThreadManage))
{
if (group.Key != null)
await group.Key.RestartDeviceAsync(group.ToArray(), false).ConfigureAwait(false);
}
}
public static async Task RemoveDeviceAsync(HashSet<long> newDeciceIds)
{
@@ -255,11 +260,18 @@ internal static class RuntimeServiceHelper
if (group.Key != null)
await group.Key.RemoveDeviceAsync(group.Value.Select(a => a.Id).ToArray()).ConfigureAwait(false);
}
foreach (var group in GlobalData.GetAllVariableBusinessDeviceRuntime().Where(a => a.Driver?.DeviceThreadManage != null).GroupBy(a => a.Driver.DeviceThreadManage))
{
if (group.Key != null)
await group.Key.RestartDeviceAsync(group.ToArray(), false).ConfigureAwait(false);
}
}
public static async Task ChangedDriverAsync(ILogger logger)
{
var channelDevice = GlobalData.IdDevices.Where(a => a.Value.Driver?.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable).Select(a => a.Value).ToArray();
var channelDevice = GlobalData.GetAllVariableBusinessDeviceRuntime();
await channelDevice.ParallelForEachAsync(async (item, token) =>
{
@@ -275,7 +287,7 @@ internal static class RuntimeServiceHelper
}
public static async Task ChangedDriverAsync(ConcurrentHashSet<IDriver> changedDriver, ILogger logger)
{
var drivers = GlobalData.IdDevices.Where(a => a.Value.Driver?.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable).Select(a => a.Value.Driver);
var drivers = GlobalData.GetAllVariableBusinessDriver();
var changedDrivers = drivers.Concat(changedDriver).Where(a => a.DisposedValue == false).Distinct().ToArray();
await changedDrivers.ParallelForEachAsync(async (driver, token) =>

View File

@@ -11,9 +11,9 @@
<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="4.0.0-beta.27" />
<!--<PackageReference Include="TouchSocket.WebApi.Swagger" Version="4.0.0-beta.27" />-->
<PackageReference Include="TouchSocket.WebApi" Version="4.0.0-beta.27" />
<PackageReference Include="TouchSocket.Dmtp" Version="4.0.0-beta.57" />
<!--<PackageReference Include="TouchSocket.WebApi.Swagger" Version="4.0.0-beta.57" />-->
<PackageReference Include="TouchSocket.WebApi" Version="4.0.0-beta.57" />
<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />
<!--<ProjectReference Include="..\..\PluginPro\ThingsGateway.Authentication\ThingsGateway.Authentication.csproj" />-->

View File

@@ -48,6 +48,14 @@
@Localizer["Check"]
</Button>
</div>
</div>
<div class="col-12 col-md-12 min-height-500">
<BootstrapLabel Value=@PropertyComponentLocalizer["BigTextScriptPluginEventDataModel"] ShowLabelTooltip="true" />
<CodeEditor IsReadonly=@(!CanWrite) ShowLineNo @bind-Value=@businessProperty.BigTextScriptPluginEventDataModel Language="csharp" Theme="vs-dark" />
</div>
</EditTemplate>

View File

@@ -19,7 +19,6 @@ using Longbow.TcpSocket;
using Microsoft.Extensions.DependencyInjection;
using System.IO.Pipelines;
using System.Net.Sockets;
using ThingsGateway.Foundation.Modbus;
@@ -40,13 +39,6 @@ public class ModbusBenchmark : IDisposable
private List<IModbusMaster> nmodbuss = new();
//private List<ModbusTcpNet> modbusTcpNets = new();
private List<ModbusTcpMaster> modbusTcpMasters = new();
private PipeOptions GetNoDelayPipeOptions()
{
return new PipeOptions(
readerScheduler: PipeScheduler.Inline,
writerScheduler: PipeScheduler.Inline,
useSynchronizationContext: false);
}
public ModbusBenchmark()
{
@@ -54,12 +46,8 @@ public class ModbusBenchmark : IDisposable
{
var clientConfig = new TouchSocket.Core.TouchSocketConfig();
//clientConfig.SetTransportOption(new TouchSocket.Sockets.TransportOption()
//{
// ReceivePipeOptions = GetNoDelayPipeOptions(),
// SendPipeOptions = GetNoDelayPipeOptions(),
//}).SetNoDelay(true);
var clientChannel = clientConfig.GetTcpClient(new ChannelOptions() { RemoteUrl = "127.0.0.1:502", MaxConcurrentCount = 10 });
var clientChannel = clientConfig.GetChannel(new ChannelOptions() { ChannelType = ChannelTypeEnum.TcpClient, RemoteUrl = "127.0.0.1:502", MaxConcurrentCount = 10 });
var thingsgatewaymodbus = new ModbusMaster()
{
//modbus协议格式
@@ -121,26 +109,7 @@ public class ModbusBenchmark : IDisposable
}
}
}
[Benchmark]
public async Task LongbowModbus()
{
List<Task> tasks = new List<Task>();
foreach (var _lgbModbusClient in _lgbModbusClients)
{
for (int i = 0; i < Program.TaskNumberOfItems; i++)
{
tasks.Add(Task.Run(async () =>
{
for (int i = 0; i < Program.NumberOfItems; i++)
{
var task = await _lgbModbusClient.ReadHoldingRegistersAsync(1, 0, 100);
}
}));
}
}
await Task.WhenAll(tasks);
}
[Benchmark]
public async Task ThingsGateway()
{
@@ -155,7 +124,7 @@ public class ModbusBenchmark : IDisposable
{
for (int i = 0; i < Program.NumberOfItems; i++)
{
var result = await thingsgatewaymodbus.ModbusReadAsync(new ModbusAddress() { FunctionCode = 3, StartAddress = 0, Length = 100 });
var result = await thingsgatewaymodbus.ModbusReadAsync(new ModbusAddress() { Station = 1, FunctionCode = 3, StartAddress = 0, Length = 100 }).ConfigureAwait(false);
if (!result.IsSuccess)
{
throw new Exception(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff") + result.ToString());
@@ -168,7 +137,27 @@ public class ModbusBenchmark : IDisposable
await Task.WhenAll(tasks);
}
[Benchmark]
public async Task LongbowModbus()
{
List<Task> tasks = new List<Task>();
foreach (var _lgbModbusClient in _lgbModbusClients)
{
for (int i = 0; i < Program.TaskNumberOfItems; i++)
{
tasks.Add(Task.Run(async () =>
{
for (int i = 0; i < Program.NumberOfItems; i++)
{
using var cts = new CancellationTokenSource(3000);
var task = await _lgbModbusClient.ReadHoldingRegistersAsync(1, 0, 100, cts.Token).ConfigureAwait(false);
}
}));
}
}
await Task.WhenAll(tasks);
}
[Benchmark]
public async Task TouchSocket()
@@ -182,7 +171,7 @@ public class ModbusBenchmark : IDisposable
{
for (int i = 0; i < Program.NumberOfItems; i++)
{
var result = await modbusTcpMaster.ReadHoldingRegistersAsync(0, 100);
var result = await modbusTcpMaster.ReadHoldingRegistersAsync(0, 100).ConfigureAwait(false);
var data = TouchSocketBitConverter.ConvertValues<byte, ushort>(result.Data.Span, EndianType.Little);
if (!result.IsSuccess)
{
@@ -208,7 +197,7 @@ public class ModbusBenchmark : IDisposable
{
for (int i = 0; i < Program.NumberOfItems; i++)
{
var result = await nmodbus.ReadHoldingRegistersAsync(1, 0, 100);
var result = await nmodbus.ReadHoldingRegistersAsync(1, 0, 100).ConfigureAwait(false);
}
}));
}

View File

@@ -17,8 +17,6 @@ using HslCommunication.Profinet.Siemens;
using S7.Net;
using System.IO.Pipelines;
using ThingsGateway.Foundation.SiemensS7;
using TouchSocket.Core;
@@ -32,13 +30,7 @@ public class S7Benchmark : IDisposable
private List<Plc> plcs = new();
private List<SiemensS7Net> siemensS7Nets = new();
private PipeOptions GetNoDelayPipeOptions()
{
return new PipeOptions(
readerScheduler: PipeScheduler.Inline,
writerScheduler: PipeScheduler.Inline,
useSynchronizationContext: false);
}
public S7Benchmark()
{
@@ -46,12 +38,8 @@ public class S7Benchmark : IDisposable
for (int i = 0; i < Program.ClientCount; i++)
{
var clientConfig = new TouchSocket.Core.TouchSocketConfig();
clientConfig.SetTransportOption(new TouchSocket.Sockets.TransportOption()
{
ReceivePipeOptions = GetNoDelayPipeOptions(),
SendPipeOptions = GetNoDelayPipeOptions(),
}).SetNoDelay(true);
var clientChannel = clientConfig.GetTcpClient(new ChannelOptions() { RemoteUrl = "127.0.0.1:102" });
var clientChannel = clientConfig.GetChannel(new ChannelOptions() { ChannelType = ChannelTypeEnum.TcpClient, RemoteUrl = "127.0.0.1:102" });
var siemensS7 = new SiemensS7Master()
{
//modbus协议格式

View File

@@ -20,9 +20,9 @@ namespace BenchmarkConsoleApp
{
internal class Program
{
public static int ClientCount = 30;
public static int TaskNumberOfItems = 10;
public static int NumberOfItems = 30;
public static int ClientCount = 3;
public static int TaskNumberOfItems = 1;
public static int NumberOfItems = 3;
private static async Task Main(string[] args)
{

View File

@@ -41,19 +41,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.15.2" />
<PackageReference Include="HslCommunication" Version="12.5.0" />
<PackageReference Include="Longbow.Modbus" Version="9.0.4" />
<PackageReference Include="BenchmarkDotNet" Version="0.15.3" />
<PackageReference Include="HslCommunication" Version="12.5.1" />
<PackageReference Include="Longbow.Modbus" Version="9.0.9" />
<PackageReference Include="NModbus" Version="3.0.81" />
<PackageReference Include="NModbus.Serial" Version="3.0.81" />
<PackageReference Include="S7netplus" Version="0.20.0" />
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="$(DefaultVersion)" />
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="$(DefaultVersion)" />
<PackageReference Include="TouchSocket.Modbus" Version="4.0.0-beta.27" />
<!--<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="$(DefaultVersion)" />
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="$(DefaultVersion)" />-->
<PackageReference Include="TouchSocket.Modbus" Version="4.0.0-beta.57" />
</ItemGroup>
<ItemGroup>
<!--<ProjectReference Include="..\..\Plugin\ThingsGateway.Foundation.Modbus\ThingsGateway.Foundation.Modbus.csproj" />
<ProjectReference Include="..\..\Plugin\ThingsGateway.Foundation.SiemensS7\ThingsGateway.Foundation.SiemensS7.csproj" />-->
<ProjectReference Include="..\..\Plugin\ThingsGateway.Foundation.Modbus\ThingsGateway.Foundation.Modbus.csproj" />
<ProjectReference Include="..\..\Plugin\ThingsGateway.Foundation.SiemensS7\ThingsGateway.Foundation.SiemensS7.csproj" />
</ItemGroup>
</Project>

View File

@@ -52,7 +52,7 @@ public class ModbusRequest
/// <summary>
/// 站号
/// </summary>
public byte Station { get; set; }
public byte Station { get; set; } = 1;
#endregion Request
}

View File

@@ -97,7 +97,9 @@ public class ModbusSlave : DeviceBase, IModbusAddress
{
return $"{base.GetAddressDescription()}{Environment.NewLine}{ModbusHelper.GetAddressDescription()}";
}
protected override void SetChannel()
{
}
/// <inheritdoc/>
public override DataHandlingAdapter GetDataAdapter()
{

View File

@@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.5.376.244" />
</ItemGroup>

View File

@@ -10,6 +10,7 @@
using ThingsGateway.Foundation.Extension.String;
using ThingsGateway.Foundation.Modbus;
using ThingsGateway.NewLife.Json.Extension;
using TouchSocket.Core;
@@ -28,14 +29,14 @@ public class ModbusTest
[Theory]
[InlineData("400045", true, "00010000002F01032C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
[InlineData("300045", true, "00010000002F01042C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
[InlineData("100045", true, "000100000009010206000000000000")]
[InlineData("000045", true, "000100000009010106000000000000")]
[InlineData("400045", false, "0001000000060106002C0001", "1", DataTypeEnum.UInt16)]
[InlineData("000045", false, "0001000000060105002CFF00", "true", DataTypeEnum.Boolean)]
[InlineData("400045;w=16", false, "0001000000090110002C0001020001", "1", DataTypeEnum.UInt16)]
[InlineData("000045;w=15", false, "000100000008010F002C00010101", "true", DataTypeEnum.Boolean)]
[InlineData("400045", true, "00020000002F01032C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
[InlineData("300045", true, "00020000002F01042C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
[InlineData("100045", true, "000200000009010206000000000000")]
[InlineData("000045", true, "000200000009010106000000000000")]
[InlineData("400045", false, "0002000000060106002C0001", "1", DataTypeEnum.UInt16)]
[InlineData("000045", false, "0002000000060105002CFF00", "true", DataTypeEnum.Boolean)]
[InlineData("400045;w=16", false, "0002000000090110002C0001020001", "1", DataTypeEnum.UInt16)]
[InlineData("000045;w=15", false, "000200000008010F002C00010101", "true", DataTypeEnum.Boolean)]
public async Task ModbusTcp_ReadWrite_OK(string address, bool read, string data, string writeData = null, DataTypeEnum dataTypeEnum = DataTypeEnum.UInt16)
{
var modbusChannel = new TouchSocketConfig().GetChannel(new ChannelOptions()

View File

@@ -10,6 +10,7 @@
using ThingsGateway.Foundation.Extension.String;
using ThingsGateway.Foundation.SiemensS7;
using ThingsGateway.NewLife.Json.Extension;
using TouchSocket.Core;
@@ -29,8 +30,8 @@ public class SiemensS7Test
[Theory]
[InlineData("M100", true, "03 00 00 1B 02 F0 80 32 03 00 00 00 01 00 02 00 06 00 00 04 01 FF 04 00 10 00 00")]
[InlineData("M100", false, "03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF", "1", DataTypeEnum.UInt16)]
[InlineData("M100", true, "03 00 00 1B 02 F0 80 32 03 00 00 00 02 00 02 00 06 00 00 04 01 FF 04 00 10 00 00")]
[InlineData("M100", false, "03 00 00 16 02 F0 80 32 03 00 00 00 02 00 02 00 01 00 00 05 01 FF", "1", DataTypeEnum.UInt16)]
public async Task SiemensS7_ReadWrite_OK(string address, bool read, string data, string writeData = null, DataTypeEnum dataTypeEnum = DataTypeEnum.UInt16)
{
var siemensS7Channel = new TouchSocketConfig().GetChannel(new ChannelOptions()

View File

@@ -8,9 +8,8 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Newtonsoft.Json.Linq;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.Plugin.QuestDB;
using ThingsGateway.Plugin.SqlDB;
@@ -23,7 +22,7 @@ internal static class Helper
{
var dest = new SQLHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.Value = JsonElementExtensions.GetValue(src.Value, true);
dest.CreateTime = DateTime.Now;
dest.CollectTime = src.CollectTime;
@@ -43,7 +42,7 @@ internal static class Helper
{
var dest = new SQLHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.Value = JsonElementExtensions.GetValue(src.Value, true);
dest.CreateTime = DateTime.Now;
dest.CollectTime = src.CollectTime;
@@ -121,8 +120,9 @@ internal static class Helper
{
var dest = new SQLRealValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.Value = JsonElementExtensions.GetValue(src.Value, true);
dest.CollectTime = src.CollectTime;
//dest.UpdateTime = DateTime.Now;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
@@ -145,8 +145,9 @@ internal static class Helper
{
var dest = new SQLRealValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.Value = JsonElementExtensions.GetValue(src.Value, true);
dest.CollectTime = src.CollectTime;
//dest.UpdateTime = DateTime.Now;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
@@ -172,7 +173,7 @@ internal static class Helper
{
var dest = new QuestDBHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.Value = JsonElementExtensions.GetValue(src.Value, true);
dest.CreateTime = DateTime.UtcNow;
dest.CollectTime = src.CollectTime < DateTime.MinValue ? UtcTime1970 : src.CollectTime;
@@ -192,7 +193,7 @@ internal static class Helper
{
var dest = new QuestDBHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.Value = JsonElementExtensions.GetValue(src.Value, true);
dest.CreateTime = DateTime.UtcNow;
dest.CollectTime = src.CollectTime < DateTime.MinValue ? UtcTime1970 : src.CollectTime;
@@ -252,26 +253,4 @@ internal static class Helper
#endregion
private static string GetValue(object src)
{
if (src != null)
{
if (src is string strValue)
{
return strValue;
}
else if (src is bool boolValue)
{
return boolValue ? "1" : "0";
}
else
{
return JToken.FromObject(src).ToString();
}
}
else
{
return string.Empty;
}
}
}

View File

@@ -39,7 +39,7 @@ public class RealDBProducerProperty : BusinessPropertyWithCacheInterval
/// <summary>
/// 历史表脚本
/// </summary>
[DynamicProperty(Remark = "必须为间隔上传,才生效")]
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public string? BigTextScriptHistoryTable { get; set; }
}

View File

@@ -85,7 +85,6 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariable
{
_db.DbMaintenance.CreateDatabase();
//必须为间隔上传
if (!_driverPropertys.BigTextScriptHistoryTable.IsNullOrEmpty())
{
DynamicSQLBase? hisModel = CSharpScriptEngineExtension.Do<DynamicSQLBase>(_driverPropertys.BigTextScriptHistoryTable);

View File

@@ -58,4 +58,9 @@ public class SQLRealValue : IPrimaryIdEntity
[AutoGenerateColumn(Order = 22, Visible = true, Sortable = true, Filterable = false)]
[SugarColumn(ColumnDescription = "采集时间")]
public DateTime CollectTime { get; set; }
//[AutoGenerateColumn(Order = 23, Visible = true, Sortable = true, Filterable = false)]
//[SugarColumn(ColumnDescription = "更新时间")]
//public DateTime UpdateTime { get; set; }
}

View File

@@ -112,7 +112,6 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariable
{
_db.DbMaintenance.CreateDatabase();
//必须为间隔上传
if (!_driverPropertys.BigTextScriptHistoryTable.IsNullOrEmpty())
{
var hisModel = CSharpScriptEngineExtension.Do<DynamicSQLBase>(_driverPropertys.BigTextScriptHistoryTable);

View File

@@ -69,13 +69,13 @@ public class SqlDBProducerProperty : BusinessPropertyWithCacheInterval
/// <summary>
/// 实时表脚本
/// </summary>
[DynamicProperty(Remark = "必须为间隔上传,才生效")]
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public string? BigTextScriptRealTable { get; set; }
/// <summary>
/// 历史表脚本
/// </summary>
[DynamicProperty(Remark = "必须为间隔上传,才生效")]
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public string? BigTextScriptHistoryTable { get; set; }
}

View File

@@ -30,7 +30,7 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheAlarm
{
internal readonly SqlHistoryAlarmProperty _driverPropertys = new();
private readonly SqlHistoryAlarmVariableProperty _variablePropertys = new();
public override bool RefreshRuntimeAlways { get; set; } = true;
/// <inheritdoc/>
public override Type DriverUIType
{

View File

@@ -102,7 +102,6 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariable
{
_db.DbMaintenance.CreateDatabase();
//必须为间隔上传
if (!_driverPropertys.BigTextScriptHistoryTable.IsNullOrEmpty())
{
var hisModel = CSharpScriptEngineExtension.Do<DynamicSQLBase>(_driverPropertys.BigTextScriptHistoryTable);

View File

@@ -8,13 +8,12 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using System.Text;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Foundation;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.Plugin.DB;
using ThingsGateway.SqlSugar;
using ThingsGateway.SqlSugar.TDengine;
@@ -155,7 +154,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariable
foreach (var item in variableGroup)
{
stringBuilder.Append($"""(NOW,"{item.CollectTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}",{item.Id},{item.IsOnline},"{GetValue(item)}"),""");
stringBuilder.Append($"""(NOW,"{item.CollectTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}",{item.Id},{item.IsOnline},"{JsonElementExtensions.GetValue(item.Value, true)}"),""");
}
stringBuilder.Remove(stringBuilder.Length - 1, 1);
}
@@ -174,28 +173,6 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariable
LogMessage?.Trace($"TableName{tableName}Count{result}watchTime: {stopwatch.ElapsedMilliseconds} ms");
}
}
private string GetValue(VariableBasicData src)
{
if (src.Value != null)
{
if (src.Value is string strValue)
{
return strValue;
}
else if (src.Value is bool boolValue)
{
return boolValue ? "1" : "0";
}
else
{
return JToken.FromObject(src.Value).ToString();
}
}
else
{
return string.Empty;
}
}
#endregion
#endif

View File

@@ -13,7 +13,7 @@
<ProjectReference Include="..\..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj">
</ProjectReference>
<ProjectReference Include="..\ThingsGateway.Foundation.Dlt645\ThingsGateway.Foundation.Dlt645.csproj">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</ProjectReference>
</ItemGroup>

View File

@@ -11,7 +11,7 @@
<ProjectReference Include="..\..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj">
</ProjectReference>
<PackageReference Include="Confluent.Kafka" Version="2.11.1" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -10,8 +10,6 @@
using Microsoft.Extensions.Localization;
using Newtonsoft.Json.Linq;
using System.Collections.Concurrent;
using ThingsGateway.Foundation.Modbus;
@@ -114,7 +112,8 @@ public class ModbusSlave : BusinessBase
try
{
await _plc.ConnectAsync(cancellationToken).ConfigureAwait(false);
if (channel.ChannelType == ChannelTypeEnum.TcpService)
await _plc.ConnectAsync(cancellationToken).ConfigureAwait(false);
}
catch
{
@@ -184,11 +183,11 @@ public class ModbusSlave : BusinessBase
var type = variableRuntime.GetPropertyValue(CurrentDevice.Id, nameof(ModbusSlaveVariableProperty.DataType));
if (Enum.TryParse(type, out DataTypeEnum result))
{
await _plc.WriteJTokenAsync(item.Key, JToken.FromObject(variableRuntime.Value), result, cancellationToken).ConfigureAwait(false);
await _plc.WriteJTokenAsync(item.Key, (variableRuntime.Value).GetJTokenFromObj(), result, cancellationToken).ConfigureAwait(false);
}
else
{
await _plc.WriteJTokenAsync(item.Key, JToken.FromObject(variableRuntime.Value), variableRuntime.DataType, cancellationToken).ConfigureAwait(false);
await _plc.WriteJTokenAsync(item.Key, (variableRuntime.Value).GetJTokenFromObj(), variableRuntime.DataType, cancellationToken).ConfigureAwait(false);
}
}
}

View File

@@ -13,7 +13,7 @@
<ProjectReference Include="..\..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj">
</ProjectReference>
<ProjectReference Include="..\ThingsGateway.Foundation.Modbus\ThingsGateway.Foundation.Modbus.csproj">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</ProjectReference>
</ItemGroup>

View File

@@ -1,5 +1,6 @@
{
"ThingsGateway.Plugin.Mqtt.MqttClientProperty": {
"BigTextScriptPluginEventDataModel": "BigTextScriptPluginEventDataModel",
"CAFile_BrowserFile": "CAFile",
"ClientCertificateFile_BrowserFile": "ClientCertificateFile",
"ClientKeyFile_BrowserFile": "ClientKeyFile",
@@ -40,6 +41,7 @@
"WebSocketUrl": "WebSocketUrl"
},
"ThingsGateway.Plugin.Mqtt.MqttServerProperty": {
"BigTextScriptPluginEventDataModel": "BigTextScriptPluginEventDataModel",
"AnonymousEnable": "AnonymousEnable",
"DeviceRpcEnable": "DeviceRpcEnable",
"IP": "IP",

View File

@@ -1,5 +1,6 @@
{
"ThingsGateway.Plugin.Mqtt.MqttClientProperty": {
"BigTextScriptPluginEventDataModel": "插件事件上传脚本",
"CAFile_BrowserFile": "CA文件",
"ClientCertificateFile_BrowserFile": "客户端证书",
"ClientKeyFile_BrowserFile": "客户端key文件",
@@ -40,6 +41,7 @@
"WebSocketUrl": "WebSocketUrl"
},
"ThingsGateway.Plugin.Mqtt.MqttServerProperty": {
"BigTextScriptPluginEventDataModel": "插件事件上传脚本",
"AnonymousEnable": "允许匿名登录",
"DeviceRpcEnable": "允许Rpc写入",
"IP": "IP",

View File

@@ -124,4 +124,8 @@ public class MqttClientProperty : BusinessPropertyWithCacheIntervalScript
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public string? BigTextScriptRpc { get; set; }
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public override string? BigTextScriptPluginEventDataModel { get; set; }
}

View File

@@ -76,4 +76,8 @@ public class MqttServerProperty : BusinessPropertyWithCacheIntervalScript
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public string? BigTextScriptRpc { get; set; }
[DynamicProperty]
[AutoGenerateColumn(Visible = true, IsVisibleWhenEdit = false, IsVisibleWhenAdd = false)]
public override string? BigTextScriptPluginEventDataModel { get; set; }
}

View File

@@ -27,21 +27,21 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<PackageReference Include="MQTTnet.AspNetCore" Version="4.3.7.1207" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="MQTTnet" Version="4.3.7.1207" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net6.0' ">
<PackageReference Include="MQTTnet.Server" Version="5.0.1.1416" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="MQTTnet.AspNetCore" Version="5.0.1.1416" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="MQTTnet" Version="5.0.1.1416" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -24,7 +24,7 @@
<ProjectReference Include="..\..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj">
</ProjectReference>
<ProjectReference Include="..\ThingsGateway.Foundation.OpcDa\ThingsGateway.Foundation.OpcDa.csproj">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</ProjectReference>
</ItemGroup>

View File

@@ -19,6 +19,7 @@ using System.Globalization;
using ThingsGateway.Foundation.OpcUa;
using ThingsGateway.Gateway.Application;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.NewLife.Reflection;
using TouchSocket.Core;
@@ -300,7 +301,7 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
{
SetDataType(tag, value);
}
var jToken = JToken.FromObject(value);
var jToken = (value).GetJTokenFromObj();
var dataValue = JsonUtils.DecoderObject(
Server.MessageContext,
tag.DataType,

View File

@@ -26,31 +26,31 @@
<ProjectReference Include="..\ThingsGateway.Foundation.OpcUa\ThingsGateway.Foundation.OpcUa.csproj" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Server" Version="1.5.376.244" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.5.376.244" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.5.376.244" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Core" Version="1.5.376.244" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Configuration" Version="1.5.376.244" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Security.Certificates" Version="1.5.376.244" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
<!--<PackageReference Include="System.Formats.Asn1" Version="8.0.2" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>-->
</ItemGroup>

View File

@@ -15,7 +15,7 @@
<ItemGroup>
<PackageReference Include="RabbitMQ.Client" Version="7.1.2" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -13,7 +13,7 @@
<ProjectReference Include="..\..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj">
</ProjectReference>
<ProjectReference Include="..\ThingsGateway.Foundation.SiemensS7\ThingsGateway.Foundation.SiemensS7.csproj">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
<PrivateAssets>contentFiles;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</ProjectReference>
</ItemGroup>

View File

@@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
namespace ThingsGateway.Server;
public class Program
{
public static async Task Main(string[] args)
{
await Task.Delay(2000).ConfigureAwait(false);
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"ThingsGateway.ScriptDebug": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:60174;http://localhost:60175"
}
}
}

View File

@@ -0,0 +1,52 @@
//------------------------------------------------------------------------------
//此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
// ------------------------------------------------------------------------------
using MQTTnet;
using Newtonsoft.Json.Linq;
using System.Text;
using ThingsGateway.Foundation;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.Plugin.Mqtt;
using TouchSocket.Core;
public class TestClientRpc : DynamicMqttClientRpcBase
{
public override async Task RPCInvokeAsync(ILog logMessage, MqttApplicationMessageReceivedEventArgs args, MqttClientProperty driverPropertys, IMqttClient mqttClient, Func<string, Dictionary<string, Dictionary<string, JToken>>, ValueTask<Dictionary<string, Dictionary<string, IOperResult>>>> getRpcResult, Func<CancellationToken, ValueTask<OperResult>> tryMqttClientAsync, CancellationToken cancellationToken)
{
if (driverPropertys.RpcWriteTopic.IsNullOrWhiteSpace()) return;
var t = string.Format(null, "{0}/+", driverPropertys.RpcWriteTopic);
if (MqttTopicFilterComparer.Compare(args.ApplicationMessage.Topic, t) != MqttTopicFilterCompareResult.IsMatch)
return;
var rpcDatas = Encoding.UTF8.GetString(args.ApplicationMessage.Payload).FromJsonNetString<Dictionary<string, Dictionary<string, JToken>>>();
if (rpcDatas == null)
return;
var mqttRpcResult = await getRpcResult(args.ClientId, rpcDatas).ConfigureAwait(false);
try
{
var isConnect = await tryMqttClientAsync(CancellationToken.None).ConfigureAwait(false);
if (isConnect.IsSuccess)
{
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{args.ApplicationMessage.Topic}/Response")
.WithPayload(mqttRpcResult.ToSystemTextJsonString(driverPropertys.JsonFormattingIndented)).Build();
await mqttClient.PublishAsync(variableMessage, cancellationToken).ConfigureAwait(false);
}
}
catch
{
}
}
}

View File

@@ -0,0 +1,263 @@

using Newtonsoft.Json.Linq;
using ThingsGateway.Foundation;
using ThingsGateway.Gateway.Application;
namespace ThingsGateway.Server;
/// <summary>
/// 插件类,默认实现了<see cref="IDevice"/>接口,继承<see cref="CollectFoundationBase"/> 实现采集插件
/// </summary>
public class TestCollectPlugin : CollectFoundationBase
{
/// <summary>
/// 调试UI Type如果不存在无需重写
/// </summary>
public override Type DriverDebugUIType => base.DriverDebugUIType;
/// <summary>
/// 插件属性UI Type继承<see cref="IPropertyUIBase"/>如果不存在无需重写
/// </summary>
public override Type DriverPropertyUIType => base.DriverPropertyUIType;
/// <summary>
/// 插件UI Type继承<see cref="IDriverUIBase"/>如果不存在无需重写
/// </summary>
public override Type DriverUIType => base.DriverUIType;
/// <summary>
/// 插件变量寄存器UI Type继承<see cref="IAddressUIBase"/>如果不存在无需重写
/// </summary>
public override Type DriverVariableAddressUIType => base.DriverVariableAddressUIType;
/// <summary>
/// 插件配置项,继承<see cref="CollectPropertyBase"/> 返回类实例
/// </summary>
public override CollectPropertyBase CollectProperties => _property;
private TestCollectProperty? _property = new();
/// <summary>
/// 在插件初始化时调用只会执行一次参数为插件默认的链路通道类如未实现可忽略l
/// </summary>
protected override Task InitChannelAsync(IChannel? channel, CancellationToken cancellationToken)
{
//做一些初始化操作
return Task.CompletedTask;
}
/// <summary>
/// 变量打包操作会在默认的AfterVariablesChangedAsync方法里执行参数为设备变量列表返回源读取变量列表
/// </summary>
protected override Task<List<VariableSourceRead>> ProtectedLoadSourceReadAsync(List<VariableRuntime> deviceVariables)
{
//实现将设备变量打包成源读取变量
//比如如果需要实现MC中的字多读功能需将多个变量地址打包成一个源读取地址和读取长度根据一系列规则添加解析标识然后在返回的整个字节数组中解析出原来的变量地址代表的数据字节
//一般可操作 VariableRuntime 类中的 index, thingsgatewaybitconvter 等属性
//一般可操作 VariableSourceRead 类中的 address, length 等属性
return Task.FromResult(new List<VariableSourceRead>());
}
/// <summary>
/// 实现<see cref="IDevice"/>
/// </summary>
public override IDevice? FoundationDevice => base.FoundationDevice;
/// <summary>
/// 特殊方法,添加<see cref="DynamicMethodAttribute"/> 特性 返回IOperResult
/// 支持<see cref="CancellationToken"/> 参数,需放到最后
/// 默认解析方式为英文分号
/// 比如rpc参数为 test1;test2解析query1="test1",query2="test2"
/// 也可以在变量地址中填入test1rpc参数传入test2解析query1="test1",query2="test2"
/// </summary>
[DynamicMethod("测试特殊方法")]
public IOperResult<string> TestMethod(string query1, string query2, CancellationToken cancellationToken)
{
return new OperResult<string>() { Content = "测试特殊方法" };
}
}
/// <summary>
/// 插件类配置
/// </summary>
public class TestCollectProperty : CollectFoundationPackPropertyBase
{
/// <summary>
/// 添加<see cref="DynamicPropertyAttribute"/> 特性如需多语言配置可添加json资源参考其他插件
/// </summary>
[DynamicProperty(Description = null, Remark = null)]
public string TestString { get; set; }
}
/// <summary>
/// 插件类,完全自定义
/// </summary>
public class TestCollectPlugin1 : CollectBase
{
/// <summary>
/// 调试UI Type如果不存在无需重写
/// </summary>
public override Type DriverDebugUIType => base.DriverDebugUIType;
/// <summary>
/// 插件属性UI Type继承<see cref="IPropertyUIBase"/>如果不存在无需重写
/// </summary>
public override Type DriverPropertyUIType => base.DriverPropertyUIType;
/// <summary>
/// 插件UI Type继承<see cref="IDriverUIBase"/>如果不存在无需重写
/// </summary>
public override Type DriverUIType => base.DriverUIType;
/// <summary>
/// 插件变量寄存器UI Type继承<see cref="IAddressUIBase"/>如果不存在无需重写
/// </summary>
public override Type DriverVariableAddressUIType => base.DriverVariableAddressUIType;
/// <summary>
/// 插件配置项,继承<see cref="CollectPropertyBase"/> 返回类实例
/// </summary>
public override CollectPropertyBase CollectProperties => _property;
private TestCollectProperty1? _property = new();
/// <summary>
/// 在插件初始化时调用只会执行一次参数为插件默认的链路通道类如未实现可忽略l
/// </summary>
protected override Task InitChannelAsync(IChannel? channel, CancellationToken cancellationToken)
{
//做一些初始化操作
return Task.CompletedTask;
}
/// <summary>
/// 变量打包操作会在默认的AfterVariablesChangedAsync方法里执行参数为设备变量列表返回源读取变量列表
/// </summary>
protected override Task<List<VariableSourceRead>> ProtectedLoadSourceReadAsync(List<VariableRuntime> deviceVariables)
{
//实现将设备变量打包成源读取变量
//比如如果需要实现MC中的字多读功能需将多个变量地址打包成一个源读取地址和读取长度根据一系列规则添加解析标识然后在返回的整个字节数组中解析出原来的变量地址代表的数据字节
//一般可操作 VariableRuntime 类中的 index, thingsgatewaybitconvter 等属性
//一般可操作 VariableSourceRead 类中的 address, length 等属性
return Task.FromResult(new List<VariableSourceRead>());
}
/// <summary>
/// 如果不实现ReadSourceAsync方法可以返回flase
/// </summary>
protected override bool VariableSourceReadsEnable => base.VariableSourceReadsEnable;
/// <summary>
/// 获取任务列表,默认会实现 TestOnline任务SetDeviceStatus任务以及 VariableSourceRead等任务VariableSourceRead任务启用条件为<see cref="VariableSourceReadsEnable"/> 为true。任务即是timer实现可通过<see cref="ScheduledTaskHelper.GetTask(string, Func{object?, CancellationToken, Task}, object?, TouchSocket.Core.ILog, CancellationToken)"/> 方法实现定时任务
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
protected override List<IScheduledTask> ProtectedGetTasks(CancellationToken cancellationToken)
{
return base.ProtectedGetTasks(cancellationToken);
}
/// <summary>
/// 实现离线重连任务
/// </summary>
/// <param name="state"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
protected override Task TestOnline(object? state, CancellationToken cancellationToken)
{
return base.TestOnline(state, cancellationToken);
}
/// <summary>
/// 返回是否成功连接设备
/// </summary>
/// <returns></returns>
public override bool IsConnected()
{
return true;
}
/// <summary>
/// 在变量发生组态变化后执行,默认会执行<see cref="ProtectedLoadSourceReadAsync"/> 方法重新获取源读取变量列表并且重新启动VariableSourceRead等任务
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override Task AfterVariablesChangedAsync(CancellationToken cancellationToken)
{
return base.AfterVariablesChangedAsync(cancellationToken);
}
/// <summary>
/// 变量寄存器的字符串描述
/// </summary>
/// <returns></returns>
public override string GetAddressDescription()
{
return base.GetAddressDescription();
}
/// <summary>
/// 设备暂停时执行,默认会暂停所有任务
/// </summary>
/// <param name="pause"></param>
public override void PauseThread(bool pause)
{
base.PauseThread(pause);
}
/// <summary>
/// 开始前执行
/// </summary>
protected override Task ProtectedStartAsync(CancellationToken cancellationToken)
{
//一般实现PLC长连接
return base.ProtectedStartAsync(cancellationToken);
}
/// <summary>
/// 写入变量,实现设备写入操作,注意执行写锁, using var writeLock =await ReadWriteLock.WriterLockAsync(cancellationToken).ConfigureAwait(false);
/// </summary>
protected override ValueTask<Dictionary<string, OperResult>> WriteValuesAsync(Dictionary<VariableRuntime, JToken> writeInfoLists, CancellationToken cancellationToken)
{
return base.WriteValuesAsync(writeInfoLists, cancellationToken);
}
/// <summary>
/// 读取源变量,在<see cref="VariableSourceReadsEnable"/> 为true时添加源读取任务任务启动时会执行
/// 一般需要更新设备变量值,调用<see cref="VariableRuntime.SetValue(object?, DateTime, bool)"/>
/// </summary>
protected override ValueTask<OperResult<ReadOnlyMemory<byte>>> ReadSourceAsync(VariableSourceRead variableSourceRead, CancellationToken cancellationToken)
{
return base.ReadSourceAsync(variableSourceRead, cancellationToken);
}
protected override Task DisposeAsync(bool disposing)
{
return base.DisposeAsync(disposing);
}
/// <summary>
/// 特殊方法,添加<see cref="DynamicMethodAttribute"/> 特性 返回IOperResult
/// 支持<see cref="CancellationToken"/> 参数,需放到最后
/// 默认解析方式为英文分号
/// 比如rpc参数为 test1;test2解析query1="test1",query2="test2"
/// 也可以在变量地址中填入test1rpc参数传入test2解析query1="test1",query2="test2"
/// </summary>
[DynamicMethod("测试特殊方法")]
public IOperResult<string> TestMethod(string query1, string query2, CancellationToken cancellationToken)
{
return new OperResult<string>() { Content = "测试特殊方法" };
}
}
/// <summary>
/// 插件类配置
/// </summary>
public class TestCollectProperty1 : CollectPropertyBase
{
/// <summary>
/// 添加<see cref="DynamicPropertyAttribute"/> 特性如需多语言配置可添加json资源参考其他插件
/// </summary>
[DynamicProperty(Description = null, Remark = null)]
public string TestString { get; set; }
}

View File

@@ -0,0 +1,56 @@
////------------------------------------------------------------------------------
////此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
//// 此代码版权除特别声明外的代码归作者本人Diego所有
//// 源代码使用协议遵循本仓库的开源协议及附加协议
//// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
//// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
//// 使用文档https://thingsgateway.cn/
//// QQ群605534569
//// ------------------------------------------------------------------------------
using System.Dynamic;
using ThingsGateway.Foundation;
using ThingsGateway.Gateway.Application;
public class TestDynamicModel : IDynamicModel
{
public IEnumerable<dynamic> GetList(IEnumerable<object> datas)
{
if (datas == null) return null;
List<ExpandoObject> deviceObjs = new List<ExpandoObject>();
//按设备名称分组
var groups = datas.Where(a => !string.IsNullOrEmpty(((AlarmVariable)a).DeviceName)).GroupBy(a => ((AlarmVariable)a).DeviceName, a => ((AlarmVariable)a));
foreach (var group in groups)
{
//按采集时间分组
var data = group.GroupBy(a => a.AlarmTime.DateTimeToUnixTimestamp());
var deviceObj = new ExpandoObject();
List<ExpandoObject> expandos = new List<ExpandoObject>();
foreach (var item in data)
{
var expando = new ExpandoObject();
expando.TryAdd("ts", item.Key);
var variableObj = new ExpandoObject();
foreach (var tag in item)
{
var alarmObj = new ExpandoObject();
alarmObj.TryAdd(nameof(tag.AlarmCode), tag.AlarmCode);
alarmObj.TryAdd(nameof(tag.AlarmText), tag.AlarmText);
alarmObj.TryAdd(nameof(tag.AlarmType), tag.AlarmType);
alarmObj.TryAdd(nameof(tag.AlarmLimit), tag.AlarmLimit);
alarmObj.TryAdd(nameof(tag.EventTime), tag.EventTime);
alarmObj.TryAdd(nameof(tag.EventType), tag.EventType);
variableObj.TryAdd(tag.Name, alarmObj);
}
expando.TryAdd("alarms", variableObj);
expandos.Add(expando);
}
deviceObj.TryAdd(group.Key, expandos);
deviceObjs.Add(deviceObj);
}
return deviceObjs;
}
}

View File

@@ -0,0 +1,46 @@

using System.Text;
using ThingsGateway.Gateway.Application;
public class TestExexcuteExpressions : IExexcuteExpressions
{
public TouchSocket.Core.ILog Logger { get; set; }
public async System.Threading.Tasks.Task<NodeOutput> ExecuteAsync(NodeInput input, System.Threading.CancellationToken cancellationToken)
{
//想上传mqtt可以自己写mqtt上传代码或者通过mqtt插件的公开方法上传
//直接获取mqttclient插件类型的第一个设备
//var mqttClient = GlobalData.ReadOnlyChannels.FirstOrDefault(a => a.Value.PluginName == "ThingsGateway.Plugin.Mqtt.MqttClient").Value?.ReadDeviceRuntimes?.FirstOrDefault().Value?.Driver as ThingsGateway.Plugin.Mqtt.MqttClient;
//if (mqttClient == null)
// throw new("mqttClient NOT FOUND");
//TopicArray topicArray = new()
//{
// Topic = "test",
// Payload = Encoding.UTF8.GetBytes("test")
//};
//var result = await mqttClient.MqttUpAsync(topicArray, default).ConfigureAwait(false);// 主题 和 负载
//if (!result.IsSuccess)
// throw new(result.ErrorMessage);
//return new NodeOutput() { Value = result };
//通过设备名称找出mqttClient插件
var mqttClient = GlobalData.ReadOnlyDevices.FirstOrDefault(a => a.Value.Name == "mqttDevice1").Value?.Driver as ThingsGateway.Plugin.Mqtt.MqttClient;
if (mqttClient == null)
throw new("mqttClient NOT FOUND");
TopicArray topicArray = new()
{
Topic = "test",
Payload = Encoding.UTF8.GetBytes("test")
};
var result = await mqttClient.MqttUpAsync(topicArray, default).ConfigureAwait(false);// 主题 和 负载
if (!result.IsSuccess)
throw new(result.ErrorMessage);
return new NodeOutput() { Value = result };
}
}

View File

@@ -0,0 +1,235 @@
using System.Collections.Concurrent;
using ThingsGateway.Foundation;
using ThingsGateway.Gateway.Application;
using ThingsGateway.NewLife.Extension;
public class TestKafkaDynamicModel1 : DynamicModelBase
{
private Dictionary<string, VariableRuntime> variableRuntimes = new();
private long id = 0;
public TestKafkaDynamicModel1()
{
var name = "测试MqttServer";
if (GlobalData.ReadOnlyDevices.TryGetValue(name, out var kafka1))
{
id = kafka1.Id;
foreach (var item in kafka1.Driver?.IdVariableRuntimes)
{
//变量备注1作为Key(AE报警SourceId)
var data1 = item.Value.GetPropertyValue(id, nameof(BusinessVariableProperty.Data1));
if (!data1.IsNullOrEmpty())
{
variableRuntimes.Add(data1, item.Value);
}
}
}
else
{
throw new Exception($"找不到设备 {name}");
}
}
private ConcurrentDictionary<Tuple<string, string, int>, DateTime> EventKeyTimes = new();
public override IEnumerable<dynamic> GetList(IEnumerable<object> datas)
{
if (datas == null) return null;
var pluginEventDatas = datas.Cast<PluginEventData>();
var opcDatas = pluginEventDatas.Select(
a =>
{
if (a.ObjectValue == null)
{
a.ObjectValue = a.Value.ToObject(Type.GetType(a.ValueType));
}
return a.ObjectValue is ThingsGateway.Plugin.OpcAe.OpcAeEventData opcData ? opcData : null;
}
).Where(a => a != null).ToList();
List<KafkaAlarmEntity> alarmEntities = new List<KafkaAlarmEntity>();
if (opcDatas.Count == 0)
{
Logger?.LogInformation("没有OPCAE数据");
return alarmEntities;
}
foreach (var opcAeEventData in opcDatas)
{
//一般只需要条件报警
//if (opcAeEventData.EventType != Opc.Ae.EventType.Condition)
// continue;
//重连时触发的事件,可以跳过不处理
//if(opcAeEventData.Refresh)
// continue;
var sourceName = opcAeEventData.SourceID;
if (variableRuntimes.TryGetValue(sourceName, out var variableRuntime))
{
var ack = opcAeEventData.EventType != Opc.Ae.EventType.Condition ? false : ((Opc.Ae.ConditionState)opcAeEventData.NewState).HasFlag(Opc.Ae.ConditionState.Acknowledged);
bool isRecover = opcAeEventData.EventType != Opc.Ae.EventType.Condition ? false : !((Opc.Ae.ConditionState)opcAeEventData.NewState).HasFlag(Opc.Ae.ConditionState.Active);
if (opcAeEventData.EventType != Opc.Ae.EventType.Condition)
{
bool alarm = (opcAeEventData.Message).Contains("raised");
if (alarm)
{
opcAeEventData.AlarmTime = opcAeEventData.Time;
EventKeyTimes.AddOrUpdate(Tuple.Create(opcAeEventData.SourceID, opcAeEventData.ConditionName, opcAeEventData.Cookie), opcAeEventData.Time, (k, v) => opcAeEventData.Time);
}
else
{
if (EventKeyTimes.TryGetValue(Tuple.Create(opcAeEventData.SourceID, opcAeEventData.ConditionName, opcAeEventData.Cookie), out var time))
opcAeEventData.AlarmTime = time;
else
opcAeEventData.AlarmTime = opcAeEventData.Time;
}
isRecover = !alarm;
}
//构建告警实体
KafkaAlarmEntity alarmEntity = new KafkaAlarmEntity
{
alarmCode = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data2)), //唯一编码
resourceCode = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data3)), //资源编码
resourceName = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data4)), //资源名称
metricCode = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data5)), //指标编码
metricName = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data6)), //指标名称
content = $"{variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data4))}{variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data6))}{opcAeEventData.Message}", //告警内容,设备名称+告警内容包含阈值信息可能opcae里没有带阈值信息那么就需要录入固定值可选Data10
alarmType = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data7)), // opcAeEventData.Severity 告警类型,子系统产生告警的类型,可能需要固定备注值
confirmedTime = ack ? opcAeEventData.Time.DateTimeToUnixTimestamp() : null, //告警确认时间
fixTime = isRecover ? opcAeEventData.Time : null, //解除告警时间
lastTime = opcAeEventData.AlarmTime, //产生告警时间
status = isRecover ? "FIXED" : "UNFIXED", //告警状态
alarmLevel = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data8)), //opcAeEventData.Severity.ToString(), //告警等级,可能需要固定备注值
subSystemCode = variableRuntime.GetPropertyValue(id, nameof(BusinessVariableProperty.Data9)), //子系统编码
type = "SUB_SYSTEM_ALARM", //默认填写字段
confirmAccount = opcAeEventData.ActorID, //告警确认人
clearAccount = opcAeEventData.ActorID, //告警清除人
processInstruction = null //告警处理说明OPCAE不带有
};
alarmEntities.Add(alarmEntity);
}
else
{
Logger?.LogInformation($"找不到相关变量{sourceName}");
}
}
return alarmEntities;
}
}
/// <summary>
/// 告警实体
/// </summary>
public class KafkaAlarmEntity
{
/// <summary>
/// 告警编码唯一 (非空)
/// 示例:"8e8a118ac452fd04da8c26fa588a7cab"
/// </summary>
public string alarmCode { get; set; }
/// <summary>
/// 资源编码,唯一编码,需要按照映射表上传 (非空)
/// 示例:"RS_A6K9MUSG19V"
/// </summary>
public string resourceCode { get; set; }
/// <summary>
/// 资源名称,需要按照映射表上传 (非空)
/// 示例:"MB-A7"
/// </summary>
public string resourceName { get; set; }
/// <summary>
/// 指标编码唯一,需要按照映射表上传 (非空)
/// 示例:"ActivePowerPa"
/// </summary>
public string metricCode { get; set; }
/// <summary>
/// 指标名称,需要按照映射表上传 (非空)
/// 示例:"有功功率Pa"
/// </summary>
public string metricName { get; set; }
/// <summary>
/// 告警内容:设备名称+告警内容(包含阈值信息) (非空)
/// 示例:"MB-A7有功功率Pa > 30"
/// </summary>
public string content { get; set; }
/// <summary>
/// 告警类型,子系统产生告警的类型 (非空)
/// 示例:"0101" 表示高限报警
/// </summary>
public string alarmType { get; set; }
/// <summary>
/// 告警确认时间 (可空,时间戳)
/// 示例1586152800000
/// </summary>
public long? confirmedTime { get; set; }
/// <summary>
/// 解除告警时间 (可空,时间戳)
/// 示例1586152800000
/// </summary>
public DateTime? fixTime { get; set; }
/// <summary>
/// 产生告警时间 (非空,时间戳)
/// 示例1586152800000
/// </summary>
public DateTime lastTime { get; set; }
/// <summary>
/// 告警状态 (非空)
/// 可选值UNFIXED新增告警、FIXED解除告警
/// </summary>
public string status { get; set; }
/// <summary>
/// 告警等级,需要按照映射表上传 (非空)
/// 示例:"1"
/// </summary>
public string alarmLevel { get; set; }
/// <summary>
/// 子系统编码 (非空)
/// 示例:"MS_NEW_PD_DCIM_001"
/// </summary>
public string subSystemCode { get; set; }
/// <summary>
/// 默认填写字段 (非空)
/// 固定值:"SUB_SYSTEM_ALARM"
/// </summary>
public string type { get; set; }
/// <summary>
/// 告警确认人 (可空)
/// 示例:"admin3"
/// </summary>
public string confirmAccount { get; set; }
/// <summary>
/// 告警清除人 (可空)
/// 示例:"admin"
/// </summary>
public string clearAccount { get; set; }
/// <summary>
/// 告警处理说明 (可空)
/// 示例:"admin"
/// </summary>
public string processInstruction { get; set; }
}

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
//此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
// ------------------------------------------------------------------------------
using ThingsGateway.Gateway.Application;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.Plugin.DB;
using ThingsGateway.SqlSugar;
using TouchSocket.Core;
public class TestSQL : DynamicSQLBase
{
public override Task DBInit(ISqlSugarClient db, CancellationToken cancellationToken)
{
db.DbMaintenance.CreateDatabase();
db.CodeFirst.InitTables<ThingsGateway.Plugin.OpcAe.OpcAeEventData>();
return Task.CompletedTask;
}
public override async Task DBInsertable(ISqlSugarClient db, IEnumerable<object> datas, CancellationToken cancellationToken)
{
var pluginEventDatas = datas.Cast<PluginEventData>();
var opcDatas = pluginEventDatas.Select(
a =>
{
if (a.ObjectValue == null)
{
a.ObjectValue = a.Value.ToObject(Type.GetType(a.ValueType));
}
return a.ObjectValue is ThingsGateway.Plugin.OpcAe.OpcAeEventData opcData ? opcData : null;
}
).Where(a => a != null).ToList();
if (opcDatas.Count == 0)
return;
Logger?.Info(opcDatas.ToSystemTextJsonString());
await db.Insertable(opcDatas).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);
}
}

View File

@@ -0,0 +1,49 @@
//------------------------------------------------------------------------------
//此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
// ------------------------------------------------------------------------------
using MQTTnet;
using MQTTnet.Server;
using Newtonsoft.Json.Linq;
using System.Text;
using ThingsGateway.Foundation;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.Plugin.Mqtt;
using TouchSocket.Core;
public class TestServerRpc : DynamicMqttServerRpcBase
{
public override async Task RPCInvokeAsync(ILog logMessage, InterceptingPublishEventArgs args, MqttServerProperty driverPropertys, MQTTnet.Server.MqttServer mqttServer, Func<string, Dictionary<string, Dictionary<string, JToken>>, ValueTask<Dictionary<string, Dictionary<string, IOperResult>>>> getRpcResult, CancellationToken cancellationToken)
{
if (driverPropertys.RpcWriteTopic.IsNullOrWhiteSpace()) return;
var t = string.Format(null, "{0}/+", driverPropertys.RpcWriteTopic);
if (MqttTopicFilterComparer.Compare(args.ApplicationMessage.Topic, t) != MqttTopicFilterCompareResult.IsMatch)
return;
var rpcDatas = Encoding.UTF8.GetString(args.ApplicationMessage.Payload).FromJsonNetString<Dictionary<string, Dictionary<string, JToken>>>();
if (rpcDatas == null)
return;
var mqttRpcResult = await getRpcResult(args.ClientId, rpcDatas).ConfigureAwait(false);
try
{
var variableMessage = new MqttApplicationMessageBuilder()
.WithTopic($"{args.ApplicationMessage.Topic}/Response")
.WithPayload(mqttRpcResult.ToSystemTextJsonString(driverPropertys.JsonFormattingIndented)).Build();
await mqttServer.InjectApplicationMessage(new InjectedMqttApplicationMessage(variableMessage), cancellationToken).ConfigureAwait(false);
}
catch
{
}
}
}

View File

@@ -0,0 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\Version.props" />
<ItemGroup>
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
</ItemGroup>
<!--直接引用-->
<Import Project="targets\PluginDebug.targets"/>
<Import Project="targets\ProPluginDebug.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayPro' "/>
<PropertyGroup>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<TargetFrameworks>net8.0;net9.0;</TargetFrameworks>
<CustomTargetFramework>$(TargetFramework)</CustomTargetFramework>
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
<ApplicationIcon>favicon.ico</ApplicationIcon>
<!--动态适用GC-->
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
<CETCompat>false</CETCompat>
<!--<TieredCompilation>false</TieredCompilation>-->
<!--使用自托管线程池-->
<!--<UseWindowsThreadPool>false</UseWindowsThreadPool> -->
<!--使用工作站GC-->
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
<!--<PlatformTarget>x86</PlatformTarget>-->
<!--editbin /LARGEADDRESSAWARE:NO ThingsGateway.Server.exe-->
</PropertyGroup>
<ItemGroup>
<Content Include="favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

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

View File

@@ -0,0 +1,9 @@
{
"urls": "http://*:5000",
"ConfigurationScanDirectories": [ "Configuration", "" ], // 扫描配置文件json文件夹自动合并该文件夹里面所有json文件
"IgnoreConfigurationFiles": [ "" ],
"ExternalAssemblies": [ "" ],
"DetailedErrors": true
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,43 @@
<Project>
<!--Admin-->
<ItemGroup>
<PackageReference Include="ThingsGateway.Admin.Razor" Version="$(Version)" />
<PackageReference Include="ThingsGateway.Admin.Application" Version="$(Version)" GeneratePathProperty="true"/>
</ItemGroup>
<Target Name="_ResolveCopyAdminLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
<ItemGroup>
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'=='ThingsGateway.Admin.Application' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
</ItemGroup>
</Target>
<Target Name="CopyAdminNugetPackages" AfterTargets="Build">
<ItemGroup>
<!-- setting up the variable for convenience -->
<AdminApplicationPackageFiles Include="$(PkgThingsGateway_Admin_Application)\Content\SeedData\Admin\*.*" />
</ItemGroup>
<PropertyGroup>
<AdminApplicationFolder>$(TargetDir)SeedData\Admin\</AdminApplicationFolder>
</PropertyGroup>
<RemoveDir Directories="$(AdminApplicationFolder)" />
<Copy SourceFiles="@(AdminApplicationPackageFiles)" DestinationFolder="$(AdminApplicationFolder)%(RecursiveDir)" />
</Target>
<Target Name="AdminPostPublish" AfterTargets="Publish">
<ItemGroup>
<!-- setting up the variable for convenience -->
<AdminFiles Include="bin\$(Configuration)\$(TargetFramework)\SeedData\**" />
</ItemGroup>
<PropertyGroup>
</PropertyGroup>
<Copy SourceFiles="@(AdminFiles)" DestinationFolder="$(PublishDir)SeedData\%(RecursiveDir)" />
</Target>
<!--Admin-->
</Project>

View File

@@ -0,0 +1,55 @@
<Project>
<!--Gateway-->
<ItemGroup>
<PackageReference Include="ThingsGateway.Gateway.Razor" Version="$(Version)" />
<PackageReference Include="ThingsGateway.Gateway.Application" Version="$(Version)" GeneratePathProperty="true"/>
</ItemGroup>
<Target Name="_ResolveCopyGatewayLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
<ItemGroup>
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'=='ThingsGateway.Gateway.Application' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
</ItemGroup>
</Target>
<Target Name="CopyGatewayNugetPackages" AfterTargets="Build">
<ItemGroup>
<!-- setting up the variable for convenience -->
<RulesEngineApplicationPackageFiles Include="$(PkgThingsGateway_Gateway_Application)\Content\SeedData\RulesEngine\*.*" />
<ManagementApplicationPackageFiles Include="$(PkgThingsGateway_Gateway_Application)\Content\SeedData\Management\*.*" />
<GatewayApplicationPackageFiles Include="$(PkgThingsGateway_Gateway_Application)\Content\SeedData\Gateway\*.*" />
</ItemGroup>
<PropertyGroup>
<RulesEngineApplicationFolder>$(TargetDir)SeedData\RulesEngine\</RulesEngineApplicationFolder>
<ManagementApplicationFolder>$(TargetDir)SeedData\Management\</ManagementApplicationFolder>
<GatewayApplicationFolder>$(TargetDir)SeedData\Gateway\</GatewayApplicationFolder>
</PropertyGroup>
<RemoveDir Directories="$(RulesEngineApplicationFolder)" />
<RemoveDir Directories="$(ManagementApplicationFolder)" />
<RemoveDir Directories="$(GatewayApplicationFolder)" />
<Copy SourceFiles="@(RulesEngineApplicationPackageFiles)" DestinationFolder="$(RulesEngineApplicationFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(ManagementApplicationPackageFiles)" DestinationFolder="$(ManagementApplicationFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(GatewayApplicationPackageFiles)" DestinationFolder="$(GatewayApplicationFolder)%(RecursiveDir)" />
</Target>
<Target Name="GatewayPostPublish" AfterTargets="Publish">
<ItemGroup>
<!-- setting up the variable for convenience -->
<GatewayFiles Include="bin\$(Configuration)\$(TargetFramework)\SeedData\**" />
</ItemGroup>
<PropertyGroup>
</PropertyGroup>
<Copy SourceFiles="@(GatewayFiles)" DestinationFolder="$(PublishDir)SeedData\%(RecursiveDir)" />
</Target>
<!--Gateway-->
</Project>

View File

@@ -0,0 +1,110 @@
<Project>
<!--插件隔离-->
<ItemGroup>
<!--Modbus 插件-->
<PackageReference Include="ThingsGateway.Plugin.Modbus" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--SiemensS7 插件-->
<PackageReference Include="ThingsGateway.Plugin.SiemensS7" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--Dlt645 插件-->
<PackageReference Include="ThingsGateway.Plugin.Dlt645" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--OpcDa 插件-->
<PackageReference Include="ThingsGateway.Plugin.OpcDa" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--OpcUa 插件-->
<PackageReference Include="ThingsGateway.Plugin.OpcUa" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--DB 插件-->
<PackageReference Include="ThingsGateway.Plugin.DB" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--Kafka 插件-->
<PackageReference Include="ThingsGateway.Plugin.Kafka" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--Mqtt 插件-->
<PackageReference Include="ThingsGateway.Plugin.Mqtt" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--RabbitMQ 插件-->
<PackageReference Include="ThingsGateway.Plugin.RabbitMQ" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--webhook 插件-->
<PackageReference Include="ThingsGateway.Plugin.Http" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
</ItemGroup>
<Target Name="CopyPluginNugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
<GatewayPluginFolder>$(TargetDir)GatewayPlugins\</GatewayPluginFolder>
</PropertyGroup>
<RemoveDir Directories="$(PluginFolder)" />
<RemoveDir Directories="$(GatewayPluginFolder)" />
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_ModbusPackageFiles Include="$(PkgThingsGateway_Plugin_Modbus)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_SiemensS7PackageFiles Include="$(PkgThingsGateway_Plugin_SiemensS7)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_Dlt645PackageFiles Include="$(PkgThingsGateway_Plugin_Dlt645)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_DBPackageFiles Include="$(PkgThingsGateway_Plugin_DB)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_KafkaPackageFiles Include="$(PkgThingsGateway_Plugin_Kafka)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_MqttPackageFiles Include="$(PkgThingsGateway_Plugin_Mqtt)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_OpcDaPackageFiles Include="$(PkgThingsGateway_Plugin_OpcDa)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_OpcUaPackageFiles Include="$(PkgThingsGateway_Plugin_OpcUa)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_RabbitMQPackageFiles Include="$(PkgThingsGateway_Plugin_RabbitMQ)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_HttpPackageFiles Include="$(PkgThingsGateway_Plugin_Http)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<Message Text="将开源插件复制到插件目录 $(GatewayPluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_ModbusPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.Modbus%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_SiemensS7PackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.SiemensS7%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_Dlt645PackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.Dlt645%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DBPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.DB%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_KafkaPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.Kafka%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MqttPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.Mqtt%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcDaPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.OpcDa%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcUaPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.OpcUa%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_RabbitMQPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.RabbitMQ%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HttpPackageFiles)" DestinationFolder="$(GatewayPluginFolder)ThingsGateway.Plugin.Http%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,114 @@
<Project>
<!--插件直接加载到程序上下文,不隔离-->
<ItemGroup>
<!--Modbus 插件-->
<PackageReference Include="ThingsGateway.Plugin.Modbus" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--SiemensS7 插件-->
<PackageReference Include="ThingsGateway.Plugin.SiemensS7" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--Dlt645 插件-->
<PackageReference Include="ThingsGateway.Plugin.Dlt645" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--OpcDa 插件-->
<PackageReference Include="ThingsGateway.Plugin.OpcDa" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--OpcUa 插件-->
<PackageReference Include="ThingsGateway.Plugin.OpcUa" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--DB 插件-->
<PackageReference Include="ThingsGateway.Plugin.DB" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--Kafka 插件-->
<PackageReference Include="ThingsGateway.Plugin.Kafka" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--Mqtt 插件-->
<PackageReference Include="ThingsGateway.Plugin.Mqtt" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--RabbitMQ 插件-->
<PackageReference Include="ThingsGateway.Plugin.RabbitMQ" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<!--webhook 插件-->
<PackageReference Include="ThingsGateway.Plugin.Http" Version="$(PluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
</ItemGroup>
<Target Name="CopyPluginNugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
<GatewayPluginFolder>$(TargetDir)GatewayPlugins\</GatewayPluginFolder>
</PropertyGroup>
<RemoveDir Directories="$(PluginFolder)" />
<RemoveDir Directories="$(GatewayPluginFolder)" />
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_ModbusPackageFiles Include="$(PkgThingsGateway_Plugin_Modbus)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_SiemensS7PackageFiles Include="$(PkgThingsGateway_Plugin_SiemensS7)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_Dlt645PackageFiles Include="$(PkgThingsGateway_Plugin_Dlt645)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_DBPackageFiles Include="$(PkgThingsGateway_Plugin_DB)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_KafkaPackageFiles Include="$(PkgThingsGateway_Plugin_Kafka)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_MqttPackageFiles Include="$(PkgThingsGateway_Plugin_Mqtt)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_OpcDaPackageFiles Include="$(PkgThingsGateway_Plugin_OpcDa)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_OpcUaPackageFiles Include="$(PkgThingsGateway_Plugin_OpcUa)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_RabbitMQPackageFiles Include="$(PkgThingsGateway_Plugin_RabbitMQ)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_HttpPackageFiles Include="$(PkgThingsGateway_Plugin_Http)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<Message Text="将开源插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_ModbusPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_SiemensS7PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_Dlt645PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DBPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_KafkaPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MqttPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcDaPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcUaPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_RabbitMQPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HttpPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,17 @@
<Project>
<ItemGroup>
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.Modbus\ThingsGateway.Plugin.Modbus.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.Dlt645\ThingsGateway.Plugin.Dlt645.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.SiemensS7\ThingsGateway.Plugin.SiemensS7.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.DB\ThingsGateway.Plugin.DB.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.Kafka\ThingsGateway.Plugin.Kafka.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.Mqtt\ThingsGateway.Plugin.Mqtt.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.OpcDa\ThingsGateway.Plugin.OpcDa.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.OpcUa\ThingsGateway.Plugin.OpcUa.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.RabbitMQ\ThingsGateway.Plugin.RabbitMQ.csproj" />
<ProjectReference Include="..\Plugin\ThingsGateway.Plugin.Http\ThingsGateway.Plugin.Http.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,32 @@
<Project>
<Target Name="PostPublish" AfterTargets="Publish">
<ItemGroup>
<!-- setting up the variable for convenience -->
<PluginsFiles Include="bin\$(Configuration)\$(TargetFramework)\Plugins\**" />
<GatewayPluginsFiles Include="bin\$(Configuration)\$(TargetFramework)\GatewayPlugins\**" />
</ItemGroup>
<PropertyGroup>
</PropertyGroup>
<Copy SourceFiles="@(PluginsFiles)" DestinationFolder="$(PublishDir)Plugins\%(RecursiveDir)" />
<Copy SourceFiles="@(GatewayPluginsFiles)" DestinationFolder="$(PublishDir)GatewayPlugins\%(RecursiveDir)" />
</Target>
<Target Name="RemoveXmlDocs1" AfterTargets="Build" Condition=" '$(Configuration)' != 'Debug' ">
<ItemGroup>
<XmlFilesToDelete Include="$(TargetDir)*.xml" />
</ItemGroup>
<Delete Files="@(XmlFilesToDelete)" />
</Target>
<Target Name="RemoveXmlDocs2" AfterTargets="Publish" Condition=" '$(Configuration)' != 'Debug' ">
<ItemGroup>
<XmlFilesToDelete Include="$(PublishDir)*.xml" />
</ItemGroup>
<Delete Files="@(XmlFilesToDelete)" />
</Target>
</Project>

View File

@@ -0,0 +1,97 @@
<Project>
<ItemGroup>
<PackageReference Include="ThingsGateway.Plugin.SyncBridge" Version="$(ProPluginVersion)" GeneratePathProperty="true">
<Private>false</Private>
<IncludeAssets> native;</IncludeAssets>
</PackageReference>
<PackageReference Include="ThingsGateway.Plugin.Inovance" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<PackageReference Include="ThingsGateway.Plugin.TIANXIN" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<PackageReference Include="ThingsGateway.Plugin.HJ212" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<PackageReference Include="ThingsGateway.Plugin.BACnet" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--AllenBradleyCip 插件-->
<PackageReference Include="ThingsGateway.Plugin.AllenBradleyCip" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--DCON 插件-->
<PackageReference Include="ThingsGateway.Plugin.DCON" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--EDPF_NT 插件-->
<PackageReference Include="ThingsGateway.Plugin.EDPF_NT" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--KELID2008 插件-->
<PackageReference Include="ThingsGateway.Plugin.KELID2008" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--LKSIS 插件-->
<PackageReference Include="ThingsGateway.Plugin.LKSIS" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--Melsec 插件-->
<PackageReference Include="ThingsGateway.Plugin.Melsec" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--Omron 插件-->
<PackageReference Include="ThingsGateway.Plugin.Omron" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<!--DKQ_A16D 插件-->
<!--<PackageReference Include="ThingsGateway.Plugin.DKQ_A16D" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />-->
<!--IDR210 插件-->
<!--<PackageReference Include="ThingsGateway.Plugin.IDR210" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />-->
<!--URF_R330 插件-->
<!--<PackageReference Include="ThingsGateway.Plugin.URF_R330" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />-->
<!--USBScaner 插件-->
<PackageReference Include="ThingsGateway.Plugin.USBScaner" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<PackageReference Include="ThingsGateway.Plugin.SECS" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<PackageReference Include="ThingsGateway.Plugin.TS550" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
<PackageReference Include="ThingsGateway.Plugin.Vigor" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets=" native;" />
</ItemGroup>
<Target Name="CopyCustomPluginNugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_InovancePackageFiles Include="$(PkgThingsGateway_Plugin_Inovance)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_TIANXINPackageFiles Include="$(PkgThingsGateway_Plugin_TIANXIN)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_HJ212PackageFiles Include="$(PkgThingsGateway_Plugin_HJ212)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_BACnetPackageFiles Include="$(PkgThingsGateway_Plugin_BACnet)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_AllenBradleyCipPackageFiles Include="$(PkgThingsGateway_Plugin_AllenBradleyCip)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_DCONPackageFiles Include="$(PkgThingsGateway_Plugin_DCON)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_EDPF_NTPackageFiles Include="$(PkgThingsGateway_Plugin_EDPF_NT)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_KELID2008PackageFiles Include="$(PkgThingsGateway_Plugin_KELID2008)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_LKSISPackageFiles Include="$(PkgThingsGateway_Plugin_LKSIS)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_MelsecPackageFiles Include="$(PkgThingsGateway_Plugin_Melsec)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_OmronPackageFiles Include="$(PkgThingsGateway_Plugin_Omron)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_DKQ_A16DPackageFiles Include="$(PkgThingsGateway_Plugin_DKQ_A16D)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_IDR210PackageFiles Include="$(PkgThingsGateway_Plugin_IDR210)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_URF_R330PackageFiles Include="$(PkgThingsGateway_Plugin_URF_R330)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_USBScanerPackageFiles Include="$(PkgThingsGateway_Plugin_USBScaner)\Content\$(PluginTargetFramework)\**\*.*" />
<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_SyncBridgePackageFiles Include="$(PkgThingsGateway_Plugin_SyncBridge)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<PropertyGroup>
<PluginFolder>$(TargetDir)GatewayPlugins\</PluginFolder>
</PropertyGroup>
<Message Text="将PRO插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_InovancePackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Inovance%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_TIANXINPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.TIANXIN%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HJ212PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.HJ212%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_BACnetPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.BACnet%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_AllenBradleyCipPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.AllenBradleyCip%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DCONPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.DCON%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_EDPF_NTPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.EDPF_NT%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_KELID2008PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.KELID2008%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_LKSISPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.LKSIS%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MelsecPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Melsec%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OmronPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Omron%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DKQ_A16DPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.DKQ_A16D%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_IDR210PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.IDR210%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_URF_R330PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.URF_R330%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_USBScanerPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.USBScaner%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_SECSPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.SECS%(RecursiveDir)" />
<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_SyncBridgePackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.SyncBridge%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,32 @@
<Project>
<ItemGroup>
<!--HUANANSFSK 插件-->
<PackageReference Include="ThingsGateway.Plugin.HUANANSFSK" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
<!--YPSFSK 插件-->
<PackageReference Include="ThingsGateway.Plugin.YPSFSK" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
</ItemGroup>
<Target Name="CopyOtherPlugin3NugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_HUANANSFSKPackageFiles Include="$(PkgThingsGateway_Plugin_HUANANSFSK)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_YPSFSKPackageFiles Include="$(PkgThingsGateway_Plugin_YPSFSK)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<PropertyGroup>
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
</PropertyGroup>
<Message Text="将SFSK插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HUANANSFSKPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_YPSFSKPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,28 @@
<Project>
<ItemGroup>
<PackageReference Include="ThingsGateway.Plugin.ModbusC1" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
<PackageReference Include="ThingsGateway.Plugin.ModbusGY" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
</ItemGroup>
<Target Name="CopyOtherPlugin1NugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_ModbusC1PackageFiles Include="$(PkgThingsGateway_Plugin_ModbusC1)\Content\$(PluginTargetFramework)\**\*.*" />
<PkgThingsGateway_Plugin_ModbusGYPackageFiles Include="$(PkgThingsGateway_Plugin_ModbusGY)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<PropertyGroup>
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
</PropertyGroup>
<Message Text="将Modbus定制插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_ModbusC1PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_ModbusGYPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,28 @@
<Project>
<ItemGroup>
<!--MqttYINGKE 插件-->
<PackageReference Include="ThingsGateway.Plugin.MqttYINGKE" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
</ItemGroup>
<Target Name="CopyOtherPlugin5NugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_MqttYINGKEPackageFiles Include="$(PkgThingsGateway_Plugin_MqttYINGKE)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<PropertyGroup>
<PluginFolder>$(TargetDir)GatewayPlugins\</PluginFolder>
</PropertyGroup>
<Message Text="将MQTTYINGKE插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MqttYINGKEPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.MqttYINGKE%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,28 @@
<Project>
<ItemGroup>
<!--MqttYINGKE 插件-->
<PackageReference Include="ThingsGateway.Plugin.IXCom29s" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
</ItemGroup>
<Target Name="CopyOtherPlugin6NugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_IXCom29sPackageFiles Include="$(PkgThingsGateway_Plugin_IXCom29s)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<PropertyGroup>
<PluginFolder>$(TargetDir)GatewayPlugins\</PluginFolder>
</PropertyGroup>
<Message Text="将IXCom29s插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_IXCom29sPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.IXCom29s%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,28 @@
<Project>
<ItemGroup>
<!--MqttYINGKE 插件-->
<PackageReference Include="ThingsGateway.Plugin.OpcAe" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
</ItemGroup>
<Target Name="CopyOtherPlugin7NugetPackages" AfterTargets="Build">
<PropertyGroup>
<PluginTargetFramework>net8.0</PluginTargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- setting up the variable for convenience -->
<PkgThingsGateway_Plugin_OpcAePackageFiles Include="$(PkgThingsGateway_Plugin_OpcAe)\Content\$(PluginTargetFramework)\**\*.*" />
</ItemGroup>
<PropertyGroup>
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
</PropertyGroup>
<Message Text="将OpcAe插件复制到插件目录 $(PluginFolder)" Importance="high" />
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcAePackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
</Target>
</Project>

View File

@@ -0,0 +1,40 @@
<Project>
<ItemGroup>
<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" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.DCON\ThingsGateway.Plugin.DCON.csproj" />
<!--<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.DKQ_A16D\ThingsGateway.Plugin.DKQ_A16D.csproj" />-->
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.EDPF_NT\ThingsGateway.Plugin.EDPF_NT.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.HJ212\ThingsGateway.Plugin.HJ212.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.HUANANSFSK\ThingsGateway.Plugin.HUANANSFSK.csproj" />
<!--<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.IDR210\ThingsGateway.Plugin.IDR210.csproj" />-->
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.KELID2008\ThingsGateway.Plugin.KELID2008.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.LEIDIAN\ThingsGateway.Plugin.LEIDIANAPI.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.LKSIS\ThingsGateway.Plugin.LKSIS.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.Melsec\ThingsGateway.Plugin.Melsec.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.ModbusC1\ThingsGateway.Plugin.ModbusC1.csproj" />
<!--<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.MqttSZJYZ\ThingsGateway.Plugin.MqttSZJYZ.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.MqttYINGKE\ThingsGateway.Plugin.MqttYINGKE.csproj" />-->
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.Omron\ThingsGateway.Plugin.Omron.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.SECS\ThingsGateway.Plugin.SECS.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.TS550\ThingsGateway.Plugin.TS550.csproj" />
<!--<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.URF_R330\ThingsGateway.Plugin.URF_R330.csproj" />-->
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.USBScaner\ThingsGateway.Plugin.USBScaner.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.Vigor\ThingsGateway.Plugin.Vigor.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.YPSFSK\ThingsGateway.Plugin.YPSFSK.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.TIANXIN\ThingsGateway.Plugin.TIANXIN.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.Inovance\ThingsGateway.Plugin.Inovance.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.ModbusGY\ThingsGateway.Plugin.ModbusGY.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.IXCom29s\ThingsGateway.Plugin.IXCom29s.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Plugin.OpcAe\ThingsGateway.Plugin.OpcAe.csproj" />
<ProjectReference Include="..\PluginPro\ThingsGateway.Foundation.OpcAe\ThingsGateway.Foundation.OpcAe.csproj" />
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More