Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7590ba4ad5 | ||
|
|
39ce18f8bb | ||
|
|
777a4f9d3f | ||
|
|
b91a938787 | ||
|
|
c903abdb1b | ||
|
|
3279bc0580 | ||
|
|
bd32c9f49e | ||
|
|
5507088e3d | ||
|
|
37ad48ae4a | ||
|
|
120c6e6d87 | ||
|
|
866e907b7e | ||
|
|
2bd8c2cb10 | ||
|
|
c6c9919178 | ||
|
|
575bf9d1e0 | ||
|
|
82a56e0285 | ||
|
|
25d5f7c132 | ||
|
|
a3e9ecf30f | ||
|
|
ec5ff0a07f | ||
|
|
be836d30c5 | ||
|
|
42b1529a5f | ||
|
|
47708c4807 | ||
|
|
d2a51e004c | ||
|
|
ab14230101 | ||
|
|
4bcf8c1f78 | ||
|
|
44d00e9da3 | ||
|
|
d7e6a4493c | ||
|
|
53e89d8c54 | ||
|
|
4497c13634 | ||
|
|
4a35fade46 | ||
|
|
6cba0601fd | ||
|
|
ed4332ea78 | ||
|
|
aba069cec5 | ||
|
|
8a82ac0a11 | ||
|
|
1cd1456d75 | ||
|
|
b791a3eb10 | ||
|
|
3b22a8b170 | ||
|
|
419e8214ca | ||
|
|
b9f8571f0f | ||
|
|
c6d9a9d7f8 | ||
|
|
310aba6ccb | ||
|
|
9bd89ac4f6 | ||
|
|
ea6a51dca9 | ||
|
|
e701bcc50c | ||
|
|
a1abf06e75 | ||
|
|
76ace394b0 | ||
|
|
4dac462f8f | ||
|
|
039672b1e7 | ||
|
|
1b26ecbbf5 | ||
|
|
f4a7e96943 | ||
|
|
a45bc2954f | ||
|
|
62f32467b7 | ||
|
|
600a1bf201 | ||
|
|
7e196e7aa6 | ||
|
|
9ad3507b66 | ||
|
|
add1bdfcf6 | ||
|
|
7ea8a7c079 | ||
|
|
28e31f5165 | ||
|
|
10a6975c5d | ||
|
|
b34ea87660 | ||
|
|
86ed69c50b | ||
|
|
02e824154c | ||
|
|
dc973c8491 | ||
|
|
0a28e3a8d3 | ||
|
|
7a48c260e1 | ||
|
|
c55c49a3a2 | ||
|
|
0fc9b06d12 | ||
|
|
d71ad5a6bf | ||
|
|
f0b3028306 |
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "Admin"]
|
||||
url = https://gitee.com/ThingsGateway/BlazorAdmin
|
||||
path = Admin
|
||||
|
||||
1
Admin
Submodule
1
Admin
Submodule
Submodule Admin added at 3b73b7283a
@@ -10,6 +10,42 @@
|
||||
|
||||
[NuGet](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
|
||||
|
||||
## 源码获取/更新
|
||||
|
||||
### 源码克隆
|
||||
|
||||
|
||||
注意因仓库包含子模块,直接下载zip包会导致子模块丢失,建议使用git clone命令
|
||||
|
||||
``` shell
|
||||
|
||||
https://gitee.com/ThingsGateway/ThingsGateway.git
|
||||
|
||||
```
|
||||
|
||||
### 源码更新
|
||||
|
||||
在vs中打开powerShell窗口,执行以下命令,或根目录下的`git_pull.bat`脚本
|
||||
|
||||
<img src="https://foruda.gitee.com/images/1736150639726525137/8ff84c29_7941935.png" width="400px" />
|
||||
|
||||
|
||||
``` shell
|
||||
|
||||
chcp 65001
|
||||
|
||||
rem 更新主仓库
|
||||
git pull
|
||||
|
||||
rem 初始化并更新所有子模块
|
||||
git submodule update --init
|
||||
|
||||
pause
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 插件列表
|
||||
|
||||
#### 采集插件
|
||||
|
||||
9
git_pull.bat
Normal file
9
git_pull.bat
Normal file
@@ -0,0 +1,9 @@
|
||||
chcp 65001
|
||||
|
||||
rem 更新主仓库
|
||||
git pull
|
||||
|
||||
rem 初始化并更新所有子模块
|
||||
git submodule update --init
|
||||
|
||||
pause
|
||||
@@ -1,48 +1,49 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<AdminVersion>7.2.0.45</AdminVersion>
|
||||
<PluginVersion>9.0.2.38</PluginVersion>
|
||||
<ProPluginVersion>9.0.2.65</ProPluginVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AdminVersion>7.2.0.64</AdminVersion>
|
||||
<GatewayVersion>7.2.3.9</GatewayVersion>
|
||||
<PluginVersion>9.0.3.10</PluginVersion>
|
||||
<ProPluginVersion>9.0.3.6</ProPluginVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
<AnalysisModeDesign>None</AnalysisModeDesign>
|
||||
<AnalysisModeDocumentation>All</AnalysisModeDocumentation>
|
||||
<AnalysisModeGlobalization>None</AnalysisModeGlobalization>
|
||||
<AnalysisModeInteroperability>All</AnalysisModeInteroperability>
|
||||
<AnalysisModeMaintainability>All</AnalysisModeMaintainability>
|
||||
<AnalysisModeNaming>None</AnalysisModeNaming>
|
||||
<AnalysisModePerformance>All</AnalysisModePerformance>
|
||||
<AnalysisModeSingleFile>All</AnalysisModeSingleFile>
|
||||
<AnalysisModeReliability>All</AnalysisModeReliability>
|
||||
<AnalysisModeSecurity>All</AnalysisModeSecurity>
|
||||
<AnalysisModeUsage>None</AnalysisModeUsage>
|
||||
<AnalysisModeStyle>None</AnalysisModeStyle>
|
||||
|
||||
<NoWarn>CS8603;CS8618;CS1591;CS8625;CS8602;CS8604;CS8600;CS8601;CS8714;CS8619;CS8629;CS8765;CS8634;CS8621;CS8767;CS8633;CS8620;CS8610;CS8631;CS8605;CS8622;CS8613;NU5100;NU5104;NU1903;NU1902;</NoWarn>
|
||||
<TargetFrameworks>net9.0;net8.0;net6.0;</TargetFrameworks>
|
||||
<LangVersion>12.0</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Authors>Diego</Authors>
|
||||
<Company>Diego</Company>
|
||||
<Product>Diego</Product>
|
||||
<Copyright>版权所有 © 2023-present Diego</Copyright>
|
||||
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
|
||||
<RepositoryType>Gitee</RepositoryType>
|
||||
<GenerateResxSourceIncludeDefaultValues>true</GenerateResxSourceIncludeDefaultValues>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(SolutionDir)Directory.Build.props" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
<AnalysisModeDesign>None</AnalysisModeDesign>
|
||||
<AnalysisModeDocumentation>All</AnalysisModeDocumentation>
|
||||
<AnalysisModeGlobalization>None</AnalysisModeGlobalization>
|
||||
<AnalysisModeInteroperability>All</AnalysisModeInteroperability>
|
||||
<AnalysisModeMaintainability>All</AnalysisModeMaintainability>
|
||||
<AnalysisModeNaming>None</AnalysisModeNaming>
|
||||
<AnalysisModePerformance>All</AnalysisModePerformance>
|
||||
<AnalysisModeSingleFile>All</AnalysisModeSingleFile>
|
||||
<AnalysisModeReliability>All</AnalysisModeReliability>
|
||||
<AnalysisModeSecurity>All</AnalysisModeSecurity>
|
||||
<AnalysisModeUsage>None</AnalysisModeUsage>
|
||||
<AnalysisModeStyle>None</AnalysisModeStyle>
|
||||
|
||||
<PropertyGroup>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>Embedded</DebugType>
|
||||
<EmbedAllSources>True</EmbedAllSources>
|
||||
</PropertyGroup>
|
||||
<NoWarn>CS8603;CS8618;CS1591;CS8625;CS8602;CS8604;CS8600;CS8601;CS8714;CS8619;CS8629;CS8765;CS8634;CS8621;CS8767;CS8633;CS8620;CS8610;CS8631;CS8605;CS8622;CS8613;NU5100;NU5104;NU1903;NU1902;</NoWarn>
|
||||
<TargetFrameworks>net9.0;net8.0;net6.0;</TargetFrameworks>
|
||||
<LangVersion>12.0</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Authors>Diego</Authors>
|
||||
<Company>Diego</Company>
|
||||
<Product>Diego</Product>
|
||||
<Copyright>版权所有 © 2023-present Diego</Copyright>
|
||||
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
|
||||
<RepositoryType>Gitee</RepositoryType>
|
||||
<GenerateResxSourceIncludeDefaultValues>true</GenerateResxSourceIncludeDefaultValues>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(SolutionDir)Directory.Build.props" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>Embedded</DebugType>
|
||||
<EmbedAllSources>True</EmbedAllSources>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -134,7 +134,11 @@ public static class CSharpScriptEngineExtension
|
||||
return runScript;
|
||||
}
|
||||
|
||||
|
||||
public static void SetExpire(string source, TimeSpan? timeSpan = null)
|
||||
{
|
||||
var field = $"{CacheKey}-{source}";
|
||||
Instance.SetExpire(field, timeSpan ?? TimeSpan.FromHours(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ using ThingsGateway.NewLife;
|
||||
using ThingsGateway.NewLife.Caching;
|
||||
using ThingsGateway.NewLife.Threading;
|
||||
|
||||
using TouchSocket.Core;
|
||||
|
||||
namespace ThingsGateway.Gateway.Application.Extensions;
|
||||
|
||||
/// <summary>
|
||||
@@ -25,6 +27,8 @@ namespace ThingsGateway.Gateway.Application.Extensions;
|
||||
/// </summary>
|
||||
public interface ReadWriteExpressions
|
||||
{
|
||||
public TouchSocket.Core.ILog? Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取新值
|
||||
/// </summary>
|
||||
@@ -125,6 +129,7 @@ public static class ExpressionEvaluatorExtension
|
||||
{_using}
|
||||
public class Script:ReadWriteExpressions
|
||||
{{
|
||||
public TouchSocket.Core.ILog? Logger {{ get; set; }}
|
||||
public object GetNewValue(object raw)
|
||||
{{
|
||||
{_body};
|
||||
@@ -134,6 +139,7 @@ public static class ExpressionEvaluatorExtension
|
||||
GC.Collect();
|
||||
Instance.Set(field, runScript);
|
||||
}
|
||||
|
||||
return runScript;
|
||||
}
|
||||
|
||||
@@ -151,6 +157,21 @@ public static class ExpressionEvaluatorExtension
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算表达式:例如:(int)raw*100,raw为原始值
|
||||
/// </summary>
|
||||
public static object GetExpressionsResult(this string expressions, object rawvalue, ILog logger)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(expressions))
|
||||
{
|
||||
return rawvalue;
|
||||
}
|
||||
var readWriteExpressions = GetReadWriteExpressions(expressions);
|
||||
readWriteExpressions.Logger = logger;
|
||||
var value = readWriteExpressions.GetNewValue(rawvalue);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行脚本获取返回值ReadWriteExpressions
|
||||
/// </summary>
|
||||
@@ -169,4 +190,9 @@ public static class ExpressionEvaluatorExtension
|
||||
|
||||
return runScript;
|
||||
}
|
||||
public static void SetExpire(string source, TimeSpan? timeSpan = null)
|
||||
{
|
||||
var field = $"{CacheKey}-{source}";
|
||||
Instance.SetExpire(field, timeSpan ?? TimeSpan.FromHours(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.NewLife.X" Version="$(AdminVersion)" />
|
||||
<ProjectReference Include="..\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<div class="p-1">
|
||||
|
||||
<BootstrapInputNumber @bind-Value=@ArrayLength ShowLabel="true" />
|
||||
<Select @bind-Value="@DataType" ShowLabel="true" IsPopover="true"/>
|
||||
<Select @bind-Value="@DataType" ShowLabel="true" IsPopover="true" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -106,10 +106,11 @@
|
||||
|
||||
</div>
|
||||
<div class="col-12 col-md-7 ">
|
||||
@if (Plc?.Logger != null || Logger!=null)
|
||||
{
|
||||
<LogConsole Logger=@(Plc?.Logger??Logger) LogPath=@LogPath HeaderText=@HeaderText></LogConsole>
|
||||
}
|
||||
<LogConsole LogLevel=@((Plc?.Logger??Logger)?.LogLevel??TouchSocket.Core.LogLevel.Trace) LogLevelChanged="(a)=>{
|
||||
var log=Plc?.Logger??Logger;
|
||||
if(log!=null)
|
||||
log.LogLevel=a;
|
||||
}" LogPath=@LogPath HeaderText=@HeaderText></LogConsole>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public partial class AdapterDebugComponent : AdapterDebugBase
|
||||
{
|
||||
if (Plc != null)
|
||||
{
|
||||
var deviceVariableSourceReads = Plc.LoadSourceRead<VariableSourceClass>(VariableRunTimes, MaxPack, 1000);
|
||||
var deviceVariableSourceReads = Plc.LoadSourceRead<VariableSourceClass>(VariableRunTimes, MaxPack, "1000");
|
||||
foreach (var item in deviceVariableSourceReads)
|
||||
{
|
||||
var result = await Plc.ReadAsync(item.RegisterAddress, item.Length);
|
||||
@@ -113,13 +113,13 @@ public partial class AdapterDebugComponent : AdapterDebugBase
|
||||
{
|
||||
DataType=DataTypeEnum.Int16,
|
||||
RegisterAddress="40001",
|
||||
IntervalTime=1000,
|
||||
IntervalTime="1000",
|
||||
},
|
||||
new VariableClass()
|
||||
{
|
||||
DataType=DataTypeEnum.Int32,
|
||||
RegisterAddress="40011",
|
||||
IntervalTime=1000,
|
||||
IntervalTime="1000",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public partial class ChannelDataDebugComponent : ComponentBase
|
||||
{
|
||||
try
|
||||
{
|
||||
ChannelData.CreateChannel(Model);
|
||||
await ChannelData.CreateChannelAsync(Model);
|
||||
if (OnConfimClick.HasDelegate)
|
||||
await OnConfimClick.InvokeAsync(Model);
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<HeaderTemplate>
|
||||
<div class="flex-fill">
|
||||
</div>
|
||||
@if (Logger!=null)
|
||||
@if (LogLevelChanged.HasDelegate)
|
||||
{
|
||||
<Select @bind-Value="@Logger.LogLevel" IsPopover></Select>
|
||||
<Select Value="@LogLevel" ValueChanged="LogLevelChanged" IsPopover></Select>
|
||||
}
|
||||
<Button Color="Color.None" style="color: var(--bs-card-title-color);" Icon=@(IsPause?"fa fa-play":"fa fa-pause") OnClick="Pause" />
|
||||
<Button IsAsync Color="Color.None" style="color: var(--bs-card-title-color);" Icon=@("fa fa-sign-out") OnClick="HandleOnExportClick" />
|
||||
|
||||
@@ -31,7 +31,10 @@ public partial class LogConsole : IDisposable
|
||||
public bool Disposed { get; set; }
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public ILog Logger { get; set; }
|
||||
public LogLevel LogLevel { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<LogLevel> LogLevelChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string HeaderText { get; set; } = "Log";
|
||||
@@ -96,7 +99,7 @@ public partial class LogConsole : IDisposable
|
||||
var result = TextFileReader.LastLog(files.FirstOrDefault().FullName, 0);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Messages = result.Content.Where(a => a.LogLevel >= Logger?.LogLevel).Select(a => new LogMessage((int)a.LogLevel, $"{a.LogTime} - {a.Message}{(a.ExceptionString.IsNullOrWhiteSpace() ? null : $"{Environment.NewLine}{a.ExceptionString}")}")).ToList();
|
||||
Messages = result.Content.Where(a => a.LogLevel >= LogLevel).Select(a => new LogMessage((int)a.LogLevel, $"{a.LogTime} - {a.Message}{(a.ExceptionString.IsNullOrWhiteSpace() ? null : $"{Environment.NewLine}{a.ExceptionString}")}")).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Razor" Version="$(AdminVersion)" />
|
||||
<ProjectReference Include="..\..\..\Admin\src\ThingsGateway.Razor\ThingsGateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using System.Linq.Expressions;
|
||||
|
||||
using ThingsGateway.Gateway.Application.Extensions;
|
||||
using ThingsGateway.NewLife.Reflection;
|
||||
|
||||
@@ -78,6 +80,38 @@ public abstract class VariableObject
|
||||
return jToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetBytes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual byte[] GetBytes(Expression<Func<object>> accessor)
|
||||
{
|
||||
if (accessor.Body == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(accessor));
|
||||
}
|
||||
|
||||
var expression = accessor.Body;
|
||||
if (expression is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert && unaryExpression.Type == typeof(object))
|
||||
{
|
||||
expression = unaryExpression.Operand;
|
||||
}
|
||||
|
||||
if (expression is not MemberExpression memberExpression)
|
||||
{
|
||||
throw new ArgumentException("Can only access properties");
|
||||
}
|
||||
// 从字典中获取与属性对应的变量信息
|
||||
if (!VariableRuntimePropertyDict.TryGetValue(memberExpression.Member.Name, out var variable))
|
||||
{
|
||||
throw new KeyNotFoundException($"Variable for {memberExpression.Member.Name} not found.");
|
||||
}
|
||||
|
||||
var func = accessor.Compile();
|
||||
|
||||
return variable.VariableClass.ThingsGatewayBitConverter.GetBytesFormData(GetExpressionsValue(func(), variable), variable.VariableClass.DataType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetVariableClass
|
||||
/// </summary>
|
||||
@@ -93,7 +127,7 @@ public abstract class VariableObject
|
||||
{
|
||||
DataType = dataType,
|
||||
RegisterAddress = pair.Value.Attribute.RegisterAddress,
|
||||
IntervalTime = 1000,
|
||||
IntervalTime = "1000",
|
||||
};
|
||||
pair.Value.VariableClass = variableClass;
|
||||
variableClasss.Add(variableClass);
|
||||
@@ -205,7 +239,7 @@ public abstract class VariableObject
|
||||
if (DeviceVariableSourceReads == null)
|
||||
{
|
||||
List<VariableClass> variableClasss = GetVariableClass();
|
||||
DeviceVariableSourceReads = Protocol.LoadSourceRead<VariableSourceClass>(variableClasss, MaxPack, 1000);
|
||||
DeviceVariableSourceReads = Protocol.LoadSourceRead<VariableSourceClass>(variableClasss, MaxPack, "1000");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class ChannelData
|
||||
/// 创建通道
|
||||
/// </summary>
|
||||
/// <param name="channelData"></param>
|
||||
public static void CreateChannel(ChannelData channelData)
|
||||
public static async Task CreateChannelAsync(ChannelData channelData)
|
||||
{
|
||||
if (channelData.Channel != null)
|
||||
{
|
||||
@@ -116,19 +116,19 @@ public class ChannelData
|
||||
switch (channelData.ChannelType)
|
||||
{
|
||||
case ChannelTypeEnum.TcpClient:
|
||||
channelData.Channel = channelData.TouchSocketConfig.GetTcpClientWithIPHost(channelData.RemoteUrl, channelData.BindUrl);
|
||||
channelData.Channel = await channelData.TouchSocketConfig.GetTcpClientWithIPHostAsync(channelData.RemoteUrl, channelData.BindUrl).ConfigureAwait(false);
|
||||
break;
|
||||
|
||||
case ChannelTypeEnum.TcpService:
|
||||
channelData.Channel = channelData.TouchSocketConfig.GetTcpServiceWithBindIPHost(channelData.BindUrl);
|
||||
channelData.Channel = await channelData.TouchSocketConfig.GetTcpServiceWithBindIPHostAsync(channelData.BindUrl).ConfigureAwait(false);
|
||||
break;
|
||||
|
||||
case ChannelTypeEnum.SerialPort:
|
||||
channelData.Channel = channelData.TouchSocketConfig.GetSerialPortWithOption(channelData.Map<SerialPortOption>());
|
||||
channelData.Channel = await channelData.TouchSocketConfig.GetSerialPortWithOptionAsync(channelData.Map<SerialPortOption>()).ConfigureAwait(false);
|
||||
break;
|
||||
|
||||
case ChannelTypeEnum.UdpSession:
|
||||
channelData.Channel = channelData.TouchSocketConfig.GetUdpSessionWithIPHost(channelData.RemoteUrl, channelData.BindUrl);
|
||||
channelData.Channel = await channelData.TouchSocketConfig.GetUdpSessionWithIPHostAsync(channelData.RemoteUrl, channelData.BindUrl).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public static class ChannelConfigExtensions
|
||||
/// <param name="serialPortOption">串口配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static IChannel? GetChannel(this TouchSocketConfig config, ChannelTypeEnum channelType, string? remoteUrl = default, string? bindUrl = default, SerialPortOption? serialPortOption = default)
|
||||
public static async ValueTask<IChannel?> GetChannelAsync(this TouchSocketConfig config, ChannelTypeEnum channelType, string? remoteUrl = default, string? bindUrl = default, SerialPortOption? serialPortOption = default)
|
||||
{
|
||||
config.ThrowIfNull(nameof(TouchSocketConfig));
|
||||
channelType.ThrowIfNull(nameof(ChannelTypeEnum));
|
||||
@@ -90,20 +90,20 @@ public static class ChannelConfigExtensions
|
||||
{
|
||||
case ChannelTypeEnum.TcpClient:
|
||||
remoteUrl.ThrowIfNull(nameof(IPHost));
|
||||
return config.GetTcpClientWithIPHost(remoteUrl, bindUrl);
|
||||
return await config.GetTcpClientWithIPHostAsync(remoteUrl, bindUrl).ConfigureAwait(false);
|
||||
|
||||
case ChannelTypeEnum.TcpService:
|
||||
bindUrl.ThrowIfNull(nameof(IPHost));
|
||||
return config.GetTcpServiceWithBindIPHost(bindUrl);
|
||||
return await config.GetTcpServiceWithBindIPHostAsync(bindUrl).ConfigureAwait(false);
|
||||
|
||||
case ChannelTypeEnum.SerialPort:
|
||||
serialPortOption.ThrowIfNull(nameof(SerialPortOption));
|
||||
return config.GetSerialPortWithOption(serialPortOption);
|
||||
return await config.GetSerialPortWithOptionAsync(serialPortOption).ConfigureAwait(false);
|
||||
|
||||
case ChannelTypeEnum.UdpSession:
|
||||
if (string.IsNullOrEmpty(remoteUrl) && string.IsNullOrEmpty(bindUrl))
|
||||
throw new ArgumentNullException(nameof(IPHost));
|
||||
return config.GetUdpSessionWithIPHost(remoteUrl, bindUrl);
|
||||
return await config.GetUdpSessionWithIPHostAsync(remoteUrl, bindUrl).ConfigureAwait(false);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
@@ -114,14 +114,14 @@ public static class ChannelConfigExtensions
|
||||
/// <param name="config">配置</param>
|
||||
/// <param name="serialPortOption">串口配置</param>
|
||||
/// <returns></returns>
|
||||
public static SerialPortChannel GetSerialPortWithOption(this TouchSocketConfig config, SerialPortOption serialPortOption)
|
||||
public static async ValueTask<SerialPortChannel> GetSerialPortWithOptionAsync(this TouchSocketConfig config, SerialPortOption serialPortOption)
|
||||
{
|
||||
serialPortOption.ThrowIfNull(nameof(SerialPortOption));
|
||||
config.SetSerialPortOption(serialPortOption);
|
||||
|
||||
//载入配置
|
||||
SerialPortChannel serialPortChannel = new SerialPortChannel();
|
||||
serialPortChannel.Setup(config);
|
||||
await serialPortChannel.SetupAsync(config).ConfigureAwait(false);
|
||||
|
||||
return serialPortChannel;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public static class ChannelConfigExtensions
|
||||
/// <param name="bindUrl">本地IP端口配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static TcpClientChannel GetTcpClientWithIPHost(this TouchSocketConfig config, string remoteUrl, string? bindUrl = default)
|
||||
public static async ValueTask<TcpClientChannel> GetTcpClientWithIPHostAsync(this TouchSocketConfig config, string remoteUrl, string? bindUrl = default)
|
||||
{
|
||||
remoteUrl.ThrowIfNull(nameof(IPHost));
|
||||
config.SetRemoteIPHost(remoteUrl);
|
||||
@@ -143,7 +143,7 @@ public static class ChannelConfigExtensions
|
||||
|
||||
//载入配置
|
||||
TcpClientChannel tcpClientChannel = new TcpClientChannel();
|
||||
tcpClientChannel.Setup(config);
|
||||
await tcpClientChannel.SetupAsync(config).ConfigureAwait(false);
|
||||
return tcpClientChannel;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public static class ChannelConfigExtensions
|
||||
/// <param name="bindUrl">本地IP端口配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static TcpServiceChannel GetTcpServiceWithBindIPHost(this TouchSocketConfig config, string bindUrl)
|
||||
public static async ValueTask<TcpServiceChannel> GetTcpServiceWithBindIPHostAsync(this TouchSocketConfig config, string bindUrl)
|
||||
{
|
||||
bindUrl.ThrowIfNull(nameof(IPHost));
|
||||
|
||||
@@ -162,7 +162,7 @@ public static class ChannelConfigExtensions
|
||||
config.SetListenIPHosts(IPHost.ParseIPHosts(urls));
|
||||
//载入配置
|
||||
TcpServiceChannel tcpServiceChannel = new TcpServiceChannel();
|
||||
tcpServiceChannel.Setup(config);
|
||||
await tcpServiceChannel.SetupAsync(config).ConfigureAwait(false);
|
||||
return tcpServiceChannel;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ public static class ChannelConfigExtensions
|
||||
/// <param name="bindUrl">本地IP端口配置</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static UdpSessionChannel GetUdpSessionWithIPHost(this TouchSocketConfig config, string? remoteUrl, string? bindUrl)
|
||||
public static async ValueTask<UdpSessionChannel> GetUdpSessionWithIPHostAsync(this TouchSocketConfig config, string? remoteUrl, string? bindUrl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(remoteUrl) && string.IsNullOrEmpty(bindUrl))
|
||||
throw new ArgumentNullException(nameof(IPHost));
|
||||
@@ -195,7 +195,7 @@ public static class ChannelConfigExtensions
|
||||
config.UseUdpConnReset();
|
||||
}
|
||||
#endif
|
||||
udpSessionChannel.Setup(config);
|
||||
await udpSessionChannel.SetupAsync(config).ConfigureAwait(false);
|
||||
return udpSessionChannel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ public interface IChannel : ISetupConfigObject, IDisposable, IClosableClient
|
||||
/// </summary>
|
||||
public bool Online { get; }
|
||||
|
||||
/// <summary>
|
||||
/// MaxSign
|
||||
/// </summary>
|
||||
public int MaxSign { get; set; }
|
||||
/// <summary>
|
||||
/// 通道启动成功后
|
||||
/// </summary>
|
||||
|
||||
@@ -36,6 +36,7 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
|
||||
{
|
||||
oldClient.TryShutdown();
|
||||
await oldClient.CloseAsync().ConfigureAwait(false);
|
||||
oldClient.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -52,6 +53,7 @@ public class DtuPlugin : PluginBase, ITcpReceivingPlugin
|
||||
{
|
||||
socket.TryShutdown();
|
||||
await socket.CloseAsync().ConfigureAwait(false);
|
||||
socket.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -17,4 +17,9 @@ public interface IDtu : ITcpService
|
||||
/// 心跳检测(大写16进制字符串)
|
||||
/// </summary>
|
||||
public string HeartbeatHexString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认Dtu注册包,utf-8字符串
|
||||
/// </summary>
|
||||
public string DtuId { get; set; }
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
|
||||
{
|
||||
WaitHandlePool.MaxSign = ushort.MaxValue;
|
||||
}
|
||||
public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
|
||||
@@ -117,8 +118,9 @@ public class SerialPortChannel : SerialPortClient, IClientChannel
|
||||
/// <inheritdoc/>
|
||||
public override string? ToString()
|
||||
{
|
||||
if (ProtectedMainSerialPort != null)
|
||||
return $"{ProtectedMainSerialPort.PortName}[{ProtectedMainSerialPort.BaudRate},{ProtectedMainSerialPort.DataBits},{ProtectedMainSerialPort.StopBits},{ProtectedMainSerialPort.Parity}]";
|
||||
var port = Config?.GetValue(SerialPortConfigExtension.SerialPortOptionProperty);
|
||||
if (port != null)
|
||||
return $"{port.PortName}[{port.BaudRate},{port.DataBits},{port.StopBits},{port.Parity}]";
|
||||
return base.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ public class TcpClientChannel : TcpClient, IClientChannel
|
||||
{
|
||||
WaitHandlePool.MaxSign = ushort.MaxValue;
|
||||
}
|
||||
public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
|
||||
|
||||
@@ -188,9 +188,11 @@ public class TcpServiceChannel : TcpServiceChannelBase<TcpSessionClientChannel>,
|
||||
/// <inheritdoc/>
|
||||
protected override TcpSessionClientChannel NewClient()
|
||||
{
|
||||
return new TcpSessionClientChannel();
|
||||
var data = new TcpSessionClientChannel();
|
||||
data.WaitHandlePool.MaxSign = MaxSign;
|
||||
return data;
|
||||
}
|
||||
|
||||
public int MaxSign { get; set; }
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OnTcpClosing(TcpSessionClientChannel socketClient, ClosingEventArgs e)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
|
||||
{
|
||||
WaitHandlePool.MaxSign = ushort.MaxValue;
|
||||
}
|
||||
public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
|
||||
@@ -84,6 +85,11 @@ public class TcpSessionClientChannel : TcpSessionClient, IClientChannel
|
||||
return EasyTask.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task ResetIdAsync(string newId)
|
||||
{
|
||||
await base.ResetIdAsync(newId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ public class UdpSessionChannel : UdpSession, IClientChannel
|
||||
{
|
||||
WaitHandlePool.MaxSign = ushort.MaxValue;
|
||||
}
|
||||
public int MaxSign { get => WaitHandlePool.MaxSign; set => WaitHandlePool.MaxSign = value; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ChannelReceivedEventHandler ChannelReceived { get; set; } = new();
|
||||
@@ -52,7 +53,7 @@ public class UdpSessionChannel : UdpSession, IClientChannel
|
||||
/// <summary>
|
||||
/// 等待池
|
||||
/// </summary>
|
||||
public WaitHandlePool<MessageBase> WaitHandlePool { get; } = new();
|
||||
public WaitHandlePool<MessageBase> WaitHandlePool { get; set; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public WaitLock WaitLock { get; } = new WaitLock();
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using ThingsGateway.NewLife.Threading;
|
||||
|
||||
namespace ThingsGateway.Foundation;
|
||||
|
||||
/// <summary>
|
||||
@@ -19,20 +21,26 @@ public class TimeTick
|
||||
/// 时间间隔(毫秒)
|
||||
/// </summary>
|
||||
private readonly int intervalMilliseconds = 1000;
|
||||
|
||||
private readonly Cron cron;
|
||||
/// <inheritdoc cref="TimeTick"/>
|
||||
public TimeTick(int intervalMilliseconds = 1000)
|
||||
public TimeTick(string delay)
|
||||
{
|
||||
if (intervalMilliseconds < 10)
|
||||
intervalMilliseconds = 10;
|
||||
LastTime = DateTime.Now.AddMilliseconds(-intervalMilliseconds);
|
||||
this.intervalMilliseconds = intervalMilliseconds;
|
||||
if (int.TryParse(delay, out intervalMilliseconds))
|
||||
{
|
||||
if (intervalMilliseconds < 10)
|
||||
intervalMilliseconds = 10;
|
||||
LastTime = DateTime.Now.AddMilliseconds(-intervalMilliseconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
cron = new Cron(delay);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上次触发时间
|
||||
/// </summary>
|
||||
public DateTime LastTime { get; private set; }
|
||||
public DateTime LastTime { get; private set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 是否触发时间刻度
|
||||
@@ -41,15 +49,34 @@ public class TimeTick
|
||||
/// <returns>是否触发时间刻度</returns>
|
||||
public bool IsTickHappen(DateTime currentTime)
|
||||
{
|
||||
var nextTime = LastTime.AddMilliseconds(intervalMilliseconds);
|
||||
var diffMilliseconds = (currentTime - nextTime).TotalMilliseconds;
|
||||
if (diffMilliseconds < 0)
|
||||
return false;
|
||||
else if (diffMilliseconds > intervalMilliseconds)
|
||||
LastTime = currentTime; //选择当前时间
|
||||
DateTime nextTime = DateTime.MinValue;
|
||||
if (cron == null)
|
||||
{
|
||||
nextTime = LastTime.AddMilliseconds(intervalMilliseconds);
|
||||
var diffMilliseconds = (currentTime - nextTime).TotalMilliseconds;
|
||||
if (diffMilliseconds < 0)
|
||||
return false;
|
||||
else if (diffMilliseconds * 2 < intervalMilliseconds)
|
||||
LastTime = nextTime;
|
||||
else
|
||||
LastTime = nextTime;//选择当前时间
|
||||
return true;
|
||||
}
|
||||
else
|
||||
LastTime = nextTime;
|
||||
return true;
|
||||
{
|
||||
nextTime = cron.GetNext(LastTime);
|
||||
if (currentTime >= nextTime)
|
||||
{
|
||||
LastTime = nextTime;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace ThingsGateway.Foundation;
|
||||
/// <inheritdoc/>
|
||||
public static class ByteExtensions
|
||||
{
|
||||
public static T[] SpliceArray<T>(this T[] array, params T[] values)
|
||||
{
|
||||
return DataTransUtil.SpliceArray<T>(array, values);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取byte数据类型的第offset位,是否为True<br />
|
||||
/// </summary>
|
||||
|
||||
@@ -51,6 +51,16 @@ public static class LoggerExtensions
|
||||
return GetDebugLogBasePath().CombinePath(channelId.ToString()).FileNameReplace();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取DEBUG日志路径
|
||||
/// </summary>
|
||||
/// <param name="channelId"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDebugLogPath(this string channelId)
|
||||
{
|
||||
return GetDebugLogBasePath().CombinePath(channelId.ToString()).FileNameReplace();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetLogBasePath
|
||||
/// </summary>
|
||||
|
||||
@@ -167,8 +167,11 @@ public static class StringExtensions
|
||||
objResult = value;
|
||||
else if (propertyType == typeof(IPAddress))
|
||||
objResult = IPAddress.Parse(value);
|
||||
else if (propertyType == typeof(object))
|
||||
objResult = value.GetJTokenFromString();
|
||||
else if (propertyType.IsEnum)
|
||||
objResult = Enum.Parse(propertyType, value);
|
||||
|
||||
else
|
||||
{
|
||||
objResult = null;
|
||||
|
||||
@@ -116,7 +116,7 @@ public interface IProtocol : IDisposable
|
||||
/// <summary>
|
||||
/// 连读寄存器打包
|
||||
/// </summary>
|
||||
List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new();
|
||||
List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, string defaultIntervalTime) where T : IVariableSource, new();
|
||||
|
||||
#endregion 变量地址解析
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ public abstract class ProtocolBase : DisposableObject, IProtocol
|
||||
#region 变量地址解析
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, int defaultIntervalTime) where T : IVariableSource, new();
|
||||
public abstract List<T> LoadSourceRead<T>(IEnumerable<IVariable> deviceVariables, int maxPack, string defaultIntervalTime) where T : IVariableSource, new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual string GetAddressDescription()
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.0" />
|
||||
<PackageReference Include="ThingsGateway.NewLife.X" Version="$(AdminVersion)" />
|
||||
<PackageReference Include="TouchSocket" Version="3.0.7" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.0.7" />
|
||||
<ProjectReference Include="..\..\..\Admin\src\ThingsGateway.NewLife.X\ThingsGateway.NewLife.X.csproj" />
|
||||
<PackageReference Include="TouchSocket" Version="3.0.10" />
|
||||
<PackageReference Include="TouchSocket.SerialPorts" Version="3.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -28,15 +28,17 @@ public static class JTokenUtil
|
||||
{
|
||||
try
|
||||
{
|
||||
if (item.IsNullOrWhiteSpace())
|
||||
return JValue.CreateNull();
|
||||
|
||||
if (bool.TryParse(item, out bool parseBool))
|
||||
return new JValue(parseBool);
|
||||
|
||||
// 尝试解析字符串为 JToken 对象
|
||||
return JToken.Parse(item);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (bool.TryParse(item, out bool parseBool))
|
||||
{
|
||||
return new JValue(parseBool);
|
||||
}
|
||||
// 解析失败时,将其转为 String 类型的 JValue
|
||||
return new JValue(item);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public interface IVariable
|
||||
/// <summary>
|
||||
/// 执行间隔
|
||||
/// </summary>
|
||||
int? IntervalTime { get; set; }
|
||||
string? IntervalTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 寄存器地址
|
||||
|
||||
@@ -31,7 +31,7 @@ public class VariableClass : IVariable
|
||||
/// <summary>
|
||||
/// 执行间隔
|
||||
/// </summary>
|
||||
public virtual int? IntervalTime { get; set; }
|
||||
public virtual string? IntervalTime { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsOnline { get; set; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>9.0.2.30</Version>
|
||||
<Version>9.0.3.6</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -23,9 +23,9 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[Route("openApi/configInfo")]
|
||||
[RolePermission]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class ConfigInfoControler : ControllerBase
|
||||
public class ConfigInfoController : ControllerBase
|
||||
{
|
||||
public ConfigInfoControler(
|
||||
public ConfigInfoController(
|
||||
IChannelService channelService,
|
||||
IVariableService variableService,
|
||||
IDeviceService deviceService)
|
||||
@@ -23,10 +23,10 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[RolePermission]
|
||||
[LoggingMonitor]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class ControlControler : ControllerBase
|
||||
public class ControlController : ControllerBase
|
||||
{
|
||||
private ISysUserService _sysUserService;
|
||||
public ControlControler(IRpcService rpcService, ISysUserService sysUserService)
|
||||
public ControlController(IRpcService rpcService, ISysUserService sysUserService)
|
||||
{
|
||||
_sysUserService = sysUserService;
|
||||
_rpcService = rpcService;
|
||||
@@ -34,6 +34,31 @@ public class ControlControler : ControllerBase
|
||||
|
||||
private IRpcService _rpcService { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清空全部缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("removeAllCache")]
|
||||
[DisplayName("清空全部缓存")]
|
||||
public void RemoveAllCache()
|
||||
{
|
||||
App.CacheService.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除通道/设备缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("removeCache")]
|
||||
[DisplayName("删除通道/设备缓存")]
|
||||
public void RemoveCache()
|
||||
{
|
||||
App.GetService<IDeviceService>().DeleteDeviceFromCache();
|
||||
App.GetService<IChannelService>().DeleteChannelFromCache();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 控制业务线程启停
|
||||
/// </summary>
|
||||
@@ -29,10 +29,10 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[Route("openApi/runtimeInfo")]
|
||||
[RolePermission]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class RuntimeInfoControler : ControllerBase
|
||||
public class RuntimeInfoController : ControllerBase
|
||||
{
|
||||
private ISysUserService _sysUserService;
|
||||
public RuntimeInfoControler(ISysUserService sysUserService)
|
||||
public RuntimeInfoController(ISysUserService sysUserService)
|
||||
{
|
||||
_sysUserService = sysUserService;
|
||||
}
|
||||
@@ -61,8 +61,7 @@ public class Device : BaseDataEntity
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "默认执行间隔")]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
[MinValue(10)]
|
||||
public virtual int IntervalTime { get; set; } = 1000;
|
||||
public virtual string IntervalTime { get; set; } = "1000";
|
||||
|
||||
/// <summary>
|
||||
/// 插件名称
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using SqlSugar;
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
@@ -25,7 +27,7 @@ namespace ThingsGateway.Gateway.Application;
|
||||
[Tenant(SqlSugarConst.DB_Custom)]
|
||||
[SugarIndex("index_device", nameof(Variable.DeviceId), OrderByType.Asc)]
|
||||
[SugarIndex("unique_variable_name", nameof(Variable.Name), OrderByType.Asc, true)]
|
||||
public class Variable : BaseDataEntity
|
||||
public class Variable : BaseDataEntity, IValidatableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备
|
||||
@@ -60,11 +62,11 @@ public class Variable : BaseDataEntity
|
||||
public virtual string? Unit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔
|
||||
/// 间隔时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "执行间隔", IsNullable = true)]
|
||||
[SugarColumn(ColumnDescription = "间隔时间", IsNullable = true)]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public virtual int? IntervalTime { get; set; }
|
||||
public virtual string? IntervalTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变量地址,可能带有额外的信息,比如<see cref="DataFormatEnum"/> ,以;分割
|
||||
@@ -122,11 +124,32 @@ public class Variable : BaseDataEntity
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public virtual bool RpcWriteEnable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 初始值
|
||||
/// </summary>
|
||||
[SugarColumn(IsJson = true, ColumnDataType = StaticConfig.CodeFirst_BigString, ColumnDescription = "初始值", IsNullable = true)]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public virtual object? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
_value = value?.ToString().GetJTokenFromString();
|
||||
else
|
||||
_value = null;
|
||||
}
|
||||
|
||||
}
|
||||
private object? _value;
|
||||
|
||||
/// <summary>
|
||||
/// 保存值
|
||||
/// 保存初始值
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "保存值", IsNullable = true)]
|
||||
[SugarColumn(ColumnDescription = "保存初始值", IsNullable = true)]
|
||||
[AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)]
|
||||
public virtual bool SaveValue { get; set; } = false;
|
||||
|
||||
@@ -395,6 +418,53 @@ public class Variable : BaseDataEntity
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public ConcurrentDictionary<long, ModelValueValidateForm>? VariablePropertyModels;
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
|
||||
if (HHAlarmEnable && HHAlarmCode == null)
|
||||
{
|
||||
yield return new ValidationResult("HHAlarmCode cannot be null when HHAlarmEnable is true", new[] { nameof(HHAlarmCode) });
|
||||
}
|
||||
if (HAlarmEnable && HAlarmCode == null)
|
||||
{
|
||||
yield return new ValidationResult("HAlarmCode cannot be null when HAlarmEnable is true", new[] { nameof(HAlarmCode) });
|
||||
}
|
||||
if (LAlarmEnable && LAlarmCode == null)
|
||||
{
|
||||
yield return new ValidationResult("LAlarmCode cannot be null when LAlarmEnable is true", new[] { nameof(LAlarmCode) });
|
||||
}
|
||||
if (LLAlarmEnable && LLAlarmCode == null)
|
||||
{
|
||||
yield return new ValidationResult("LLAlarmCode cannot be null when LLAlarmEnable is true", new[] { nameof(LLAlarmCode) });
|
||||
}
|
||||
|
||||
if (HHAlarmEnable && HAlarmEnable && HHAlarmCode <= HAlarmCode)
|
||||
{
|
||||
yield return new ValidationResult("HHAlarmCode must be greater than HAlarmCode", new[] { nameof(HHAlarmCode), nameof(HAlarmCode) });
|
||||
}
|
||||
if (HAlarmEnable && LAlarmEnable && HAlarmCode <= LAlarmCode)
|
||||
{
|
||||
yield return new ValidationResult("HAlarmCode must be greater than LAlarmCode", new[] { nameof(HAlarmCode), nameof(LAlarmCode) });
|
||||
}
|
||||
if (LAlarmEnable && LLAlarmEnable && LAlarmCode <= LLAlarmCode)
|
||||
{
|
||||
yield return new ValidationResult("LAlarmCode must be greater than LLAlarmCode", new[] { nameof(LAlarmCode), nameof(LLAlarmCode) });
|
||||
}
|
||||
|
||||
if (HHAlarmEnable && LAlarmEnable && HHAlarmCode <= LAlarmCode)
|
||||
{
|
||||
yield return new ValidationResult("HHAlarmCode should be greater than or less than LAlarmCode", new[] { nameof(HHAlarmCode), nameof(LAlarmCode) });
|
||||
}
|
||||
if (HHAlarmEnable && LLAlarmEnable && HHAlarmCode <= LLAlarmCode)
|
||||
{
|
||||
yield return new ValidationResult("HHAlarmCode should be greater than or less than LLAlarmCode", new[] { nameof(HHAlarmCode), nameof(LLAlarmCode) });
|
||||
}
|
||||
if (HAlarmEnable && LLAlarmEnable && HAlarmCode <= LLAlarmCode)
|
||||
{
|
||||
yield return new ValidationResult("HAlarmCode should be greater than or less than LLAlarmCode", new[] { nameof(HAlarmCode), nameof(LLAlarmCode) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelValueValidateForm
|
||||
|
||||
@@ -182,14 +182,6 @@ internal sealed class AlarmHostedService : BackgroundService, IAlarmHostedServic
|
||||
return AlarmTypeEnum.H; // 返回高报警类型枚举
|
||||
}
|
||||
|
||||
// 检查是否启用了低报警功能,并且变量的值小于低报警的限制值
|
||||
if (tag.LAlarmEnable && tag.Value.ToDecimal() < tag.LAlarmCode.ToDecimal())
|
||||
{
|
||||
limit = tag.LAlarmCode.ToString()!; // 将报警限制值设置为低报警的限制值
|
||||
expressions = tag.LRestrainExpressions!; // 获取低报警的约束表达式
|
||||
text = tag.LAlarmText!; // 获取低报警时的报警文本
|
||||
return AlarmTypeEnum.L; // 返回低报警类型枚举
|
||||
}
|
||||
|
||||
// 检查是否启用了低低报警功能,并且变量的值小于低低报警的限制值
|
||||
if (tag.LLAlarmEnable && tag.Value.ToDecimal() < tag.LLAlarmCode.ToDecimal())
|
||||
@@ -200,6 +192,16 @@ internal sealed class AlarmHostedService : BackgroundService, IAlarmHostedServic
|
||||
return AlarmTypeEnum.LL; // 返回低低报警类型枚举
|
||||
}
|
||||
|
||||
|
||||
// 检查是否启用了低报警功能,并且变量的值小于低报警的限制值
|
||||
if (tag.LAlarmEnable && tag.Value.ToDecimal() < tag.LAlarmCode.ToDecimal())
|
||||
{
|
||||
limit = tag.LAlarmCode.ToString()!; // 将报警限制值设置为低报警的限制值
|
||||
expressions = tag.LRestrainExpressions!; // 获取低报警的约束表达式
|
||||
text = tag.LAlarmText!; // 获取低报警时的报警文本
|
||||
return AlarmTypeEnum.L; // 返回低报警类型枚举
|
||||
}
|
||||
|
||||
return null; // 如果不符合任何报警条件,则返回null
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ internal sealed class BusinessDeviceHostedService : DeviceHostedService, IBusine
|
||||
{
|
||||
// 创建新的设备驱动并获取对应的通道线程
|
||||
DriverBase newDriverBase = dev.CreateDriver(PluginService);
|
||||
var newChannelThread = GetChannelThread(newDriverBase);
|
||||
var newChannelThread = await GetChannelThreadAsync(newDriverBase).ConfigureAwait(false);
|
||||
|
||||
// 如果找到了对应的通道线程
|
||||
if (newChannelThread != null)
|
||||
@@ -297,21 +297,21 @@ internal sealed class BusinessDeviceHostedService : DeviceHostedService, IBusine
|
||||
_logger.LogInformation(BusinessDeviceHostedServiceLocalizer["DeviceRuntimeGeted"]);
|
||||
var idSet = deviceRunTimes.Where(a => a.RedundantEnable && a.RedundantDeviceId != null).Select(a => a.RedundantDeviceId ?? 0).ToHashSet().ToDictionary(a => a);
|
||||
var result = deviceRunTimes.Where(a => !idSet.ContainsKey(a.Id));
|
||||
result.ParallelForEach(businessDeviceRunTime =>
|
||||
{
|
||||
if (!_stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
DriverBase driverBase = businessDeviceRunTime.CreateDriver(PluginService);
|
||||
GetChannelThread(driverBase);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, Localizer["InitError", businessDeviceRunTime.Name]);
|
||||
}
|
||||
}
|
||||
});
|
||||
await result.ParallelForEachAsync(async (businessDeviceRunTime, token) =>
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
DriverBase driverBase = businessDeviceRunTime.CreateDriver(PluginService);
|
||||
await GetChannelThreadAsync(driverBase).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, Localizer["InitError", businessDeviceRunTime.Name]);
|
||||
}
|
||||
}
|
||||
}, Environment.ProcessorCount / 2 == 0 ? 1 : Environment.ProcessorCount / 2, _stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
|
||||
@@ -197,7 +197,7 @@ internal sealed class CollectDeviceHostedService : DeviceHostedService, ICollect
|
||||
{
|
||||
// 创建新的设备驱动并获取对应的通道线程
|
||||
DriverBase newDriverBase = dev.CreateDriver(PluginService);
|
||||
var newChannelThread = GetChannelThread(newDriverBase);
|
||||
var newChannelThread = await GetChannelThreadAsync(newDriverBase).ConfigureAwait(false);
|
||||
|
||||
// 如果找到了对应的通道线程
|
||||
if (newChannelThread != null)
|
||||
@@ -205,47 +205,9 @@ internal sealed class CollectDeviceHostedService : DeviceHostedService, ICollect
|
||||
// 如果设备已更改,则执行启动前的操作
|
||||
if (isChanged)
|
||||
{
|
||||
try
|
||||
{
|
||||
//添加保存数据变量读取操作
|
||||
var saveVariable = dev.VariableRunTimes.Where(a => a.Value.SaveValue).ToDictionary(a => a.Value.Id, a => a.Value);
|
||||
|
||||
if (saveVariable.Count > 0)
|
||||
{
|
||||
var cacheDb = CacheDBUtil.GetCache(typeof(CacheDBItem<JToken>), nameof(VariableRunTime), nameof(VariableRunTime.SaveValue));
|
||||
var varList = await cacheDb.DBProvider.Queryable<CacheDBItem<JToken>>().ToListAsync().ConfigureAwait(false);
|
||||
|
||||
for (int i = 0; i < varList.Count; i++)
|
||||
{
|
||||
var varValue = varList[i];
|
||||
if (saveVariable.TryGetValue(varValue.Id, out var variable))
|
||||
{
|
||||
if (varValue.Value is JValue jValue)
|
||||
{
|
||||
variable.Value = jValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
variable.Value = varValue.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheDb.SafeDispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "SaveValue");
|
||||
}
|
||||
|
||||
await OnCollectDeviceStarting().ConfigureAwait(false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// 启动新的通道线程
|
||||
@@ -323,7 +285,6 @@ internal sealed class CollectDeviceHostedService : DeviceHostedService, ICollect
|
||||
await OnCollectDeviceStarting().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ReadValue().ConfigureAwait(false);
|
||||
await StartAllChannelThreadsAsync().ConfigureAwait(false);
|
||||
await OnCollectDeviceStarted().ConfigureAwait(false);
|
||||
_ = Task.Run(() =>
|
||||
@@ -343,52 +304,6 @@ internal sealed class CollectDeviceHostedService : DeviceHostedService, ICollect
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReadValue()
|
||||
{
|
||||
try
|
||||
{
|
||||
//添加保存数据变量读取操作
|
||||
var saveVariable = GlobalData.ReadOnlyVariables.Where(a => a.Value.SaveValue).ToDictionary(a => a.Value.Id, a => a.Value);
|
||||
var cacheDb = CacheDBUtil.GetCache(typeof(CacheDBItem<JToken>), nameof(VariableRunTime), nameof(VariableRunTime.SaveValue));
|
||||
cacheDb.InitDb();
|
||||
|
||||
{
|
||||
var varList = await cacheDb.DBProvider.Queryable<CacheDBItem<JToken>>().ToListAsync().ConfigureAwait(false);
|
||||
List<long> ids = new List<long>();
|
||||
for (int i = 0; i < varList.Count; i++)
|
||||
{
|
||||
var varValue = varList[i];
|
||||
var has = saveVariable.Count > 0;
|
||||
if (has && saveVariable.TryGetValue(varValue.Id, out var variable))
|
||||
{
|
||||
if (varValue.Value is JValue jValue)
|
||||
{
|
||||
variable.Value = jValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
variable.Value = varValue.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ids.Add(varValue.Id);
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.Count > 0)
|
||||
{
|
||||
await cacheDb.DBProvider.Deleteable<CacheDBItem<JToken>>(ids).ExecuteCommandAsync().ConfigureAwait(false);
|
||||
}
|
||||
cacheDb.SafeDispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "SaveValue");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task StopAsync(bool removeDevice)
|
||||
{
|
||||
@@ -436,22 +351,12 @@ internal sealed class CollectDeviceHostedService : DeviceHostedService, ICollect
|
||||
try
|
||||
{
|
||||
//添加保存数据变量读取操作
|
||||
var saveVariable = DriverBases.SelectMany(a => a.CurrentDevice.VariableRunTimes).Where(a => a.Value.SaveValue).Select(a =>
|
||||
{
|
||||
return new CacheDBItem<JToken>()
|
||||
{
|
||||
Id = a.Value.Id,
|
||||
Value = JToken.FromObject(a.Value.Value)
|
||||
};
|
||||
}).ToList();
|
||||
var saveVariable = DriverBases.SelectMany(a => a.CurrentDevice.VariableRunTimes).Where(a => a.Value.SaveValue).Select(a => (Variable)a.Value).ToList();
|
||||
|
||||
if (saveVariable.Count > 0)
|
||||
{
|
||||
var cacheDb = CacheDBUtil.GetCache(typeof(CacheDBItem<JToken>), nameof(VariableRunTime), nameof(VariableRunTime.SaveValue));
|
||||
|
||||
await cacheDb.DBProvider.Fastest<CacheDBItem<JToken>>().PageSize(100000).BulkMergeAsync(saveVariable).ConfigureAwait(false);
|
||||
|
||||
cacheDb.SafeDispose();
|
||||
using var db = DbContext.Db.GetConnectionScopeWithAttr<Variable>().CopyNew();
|
||||
var result = await db.Updateable<Variable>(saveVariable).UpdateColumns(a => a.Value).ExecuteCommandAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -486,22 +391,22 @@ collectDeviceRunTimes.SelectMany(a =>
|
||||
.Select(b => b.Value.WriteExpressions)))
|
||||
|
||||
.Distinct().ToList();
|
||||
result.ParallelForEach(collectDeviceRunTime =>
|
||||
{
|
||||
if (!_stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
DriverBase driverBase = collectDeviceRunTime.CreateDriver(PluginService);
|
||||
GetChannelThread(driverBase);
|
||||
await result.ParallelForEachAsync(async (collectDeviceRunTime, token) =>
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
DriverBase driverBase = collectDeviceRunTime.CreateDriver(PluginService);
|
||||
await GetChannelThreadAsync(driverBase).ConfigureAwait(false);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, Localizer["InitError", collectDeviceRunTime.Name]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, Localizer["InitError", collectDeviceRunTime.Name]);
|
||||
}
|
||||
}
|
||||
}, Environment.ProcessorCount / 2 == 0 ? 1 : Environment.ProcessorCount / 2, _stoppingToken).ConfigureAwait(false);
|
||||
|
||||
scripts.ParallelForEach(script =>
|
||||
{
|
||||
|
||||
@@ -122,7 +122,7 @@ internal abstract class DeviceHostedService : BackgroundService, IDeviceHostedSe
|
||||
|
||||
//初始化
|
||||
DriverBase newDriverBase = dev.CreateDriver(PluginService);
|
||||
var newChannelThread = GetChannelThread(newDriverBase);
|
||||
var newChannelThread = await GetChannelThreadAsync(newDriverBase).ConfigureAwait(false);
|
||||
if (newChannelThread != null)
|
||||
{
|
||||
await StartChannelThreadAsync(newChannelThread).ConfigureAwait(false);
|
||||
@@ -224,17 +224,18 @@ internal abstract class DeviceHostedService : BackgroundService, IDeviceHostedSe
|
||||
});
|
||||
}
|
||||
|
||||
private WaitLock NewChannelLock = new();
|
||||
/// <summary>
|
||||
/// 根据设备生成或获取通道线程管理器
|
||||
/// </summary>
|
||||
/// <param name="driverBase">驱动程序实例</param>
|
||||
/// <returns>通道线程管理器</returns>
|
||||
protected ChannelThread GetChannelThread(DriverBase driverBase)
|
||||
protected async ValueTask<ChannelThread> GetChannelThreadAsync(DriverBase driverBase)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = driverBase.CurrentDevice.ChannelId;
|
||||
lock (ChannelThreads)
|
||||
await NewChannelLock.WaitAsync().ConfigureAwait(false);
|
||||
{
|
||||
// 尝试从现有的通道线程管理器列表中查找匹配的通道线程
|
||||
var channelThread = ChannelThreads.FirstOrDefault(t => t.ChannelId == channelId);
|
||||
@@ -242,22 +243,29 @@ internal abstract class DeviceHostedService : BackgroundService, IDeviceHostedSe
|
||||
{
|
||||
// 如果找到了匹配的通道线程,则将驱动程序添加到该线程中
|
||||
channelThread.AddDriver(driverBase);
|
||||
channelThread.Channel?.Setup(channelThread.FoundataionConfig.Clone());
|
||||
if (channelThread.Channel != null)
|
||||
{
|
||||
await channelThread.Channel.SetupAsync(channelThread.FoundataionConfig?.Clone()).ConfigureAwait(false);
|
||||
}
|
||||
return channelThread;
|
||||
}
|
||||
|
||||
// 如果未找到匹配的通道线程,则创建一个新的通道线程
|
||||
return NewChannelThread(driverBase, channelId);
|
||||
return await NewChannelThreadAsync(driverBase, channelId).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
driverBase.SafeDispose();
|
||||
_logger.LogWarning(ex, nameof(GetChannelThread));
|
||||
_logger.LogWarning(ex, nameof(GetChannelThreadAsync));
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
NewChannelLock.Release();
|
||||
}
|
||||
// 创建新的通道线程的内部方法
|
||||
ChannelThread NewChannelThread(DriverBase driverBase, long channelId)
|
||||
async ValueTask<ChannelThread> NewChannelThreadAsync(DriverBase driverBase, long channelId)
|
||||
{
|
||||
// 根据通道ID获取通道信息
|
||||
var channel = ChannelService.GetChannelById(channelId);
|
||||
@@ -290,13 +298,19 @@ internal abstract class DeviceHostedService : BackgroundService, IDeviceHostedSe
|
||||
var wts = Math.Max(ChannelThreads.Count, 10) * 10;
|
||||
ThreadPool.SetMaxThreads(wts, wts);
|
||||
|
||||
|
||||
var config = new TouchSocketConfig();
|
||||
var log= new LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Warning };
|
||||
// 配置容器中注册日志记录器实例
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(log));
|
||||
var ichannel = await config.GetChannelAsync(channel.ChannelType, channel.RemoteUrl, channel.BindUrl, channel.Adapt<SerialPortOption>()).ConfigureAwait(false);
|
||||
// 创建新的通道线程,并将驱动程序添加到其中
|
||||
ChannelThread channelThread = new ChannelThread(channel, (a =>
|
||||
{
|
||||
return a.GetChannel(channel.ChannelType, channel.RemoteUrl, channel.BindUrl, channel.Adapt<SerialPortOption>());
|
||||
}));
|
||||
ChannelThread channelThread = new ChannelThread(channel, config, ichannel, log);
|
||||
channelThread.AddDriver(driverBase);
|
||||
channelThread.Channel?.Setup(channelThread.FoundataionConfig.Clone());
|
||||
if (channelThread.Channel != null)
|
||||
{
|
||||
await channelThread.Channel.SetupAsync(channelThread.FoundataionConfig?.Clone()).ConfigureAwait(false);
|
||||
}
|
||||
ChannelThreads.Add(channelThread);
|
||||
return channelThread;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
{
|
||||
"ThingsGateway.Gateway.Application.BusinessUpdateEnum": {
|
||||
"Change": "Change",
|
||||
"Interval": "Interval",
|
||||
"IntervalOrChange": "IntervalOrChange"
|
||||
},
|
||||
|
||||
|
||||
"ThingsGateway.Gateway.Application.ConfigInfoControler": {
|
||||
"ConfigInfoControler": "Get configuration information",
|
||||
"ThingsGateway.Gateway.Application.ConfigInfoController": {
|
||||
"ConfigInfoController": "Get configuration information",
|
||||
"GetChannelList": "Get channel information",
|
||||
"GetCollectDeviceList": "Get device information",
|
||||
"GetVariableList": "Get variable information"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ControlControler": {
|
||||
"ControlControler": "Device control",
|
||||
"ThingsGateway.Gateway.Application.ControlController": {
|
||||
"ControlController": "Device control",
|
||||
"PauseCollectThread": "Control collection thread start/stop",
|
||||
"PauseBusinessThread": "Control business thread start/stop",
|
||||
"RestartCollectDeviceThread": "Restart collection thread",
|
||||
"RestartBusinessDeviceThread": "Restart business thread",
|
||||
"WriteDeviceMethods": "Write variables"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.RuntimeInfoControler": {
|
||||
"RuntimeInfoControler": "Get runtime information",
|
||||
"ThingsGateway.Gateway.Application.RuntimeInfoController": {
|
||||
"RuntimeInfoController": "Get runtime information",
|
||||
"GetCollectDeviceList": "Get device information",
|
||||
"GetVariableList": "Get variable information",
|
||||
"GetRealAlarmList": "Get real-time alarm information",
|
||||
@@ -361,6 +365,7 @@
|
||||
"ReadExpressions": "ReadExpressions",
|
||||
"WriteExpressions": "WriteExpressions",
|
||||
"RpcWriteEnable": "RpcWriteEnable",
|
||||
"Value": "InitValue",
|
||||
"SaveValue": "SaveValue",
|
||||
"AlarmDelay": "AlarmDelay",
|
||||
"BoolOpenAlarmEnable": "BoolOpenAlarmEnable",
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
{
|
||||
|
||||
|
||||
"ThingsGateway.Gateway.Application.ConfigInfoControler": {
|
||||
"ConfigInfoControler": "获取配置信息",
|
||||
"ThingsGateway.Gateway.Application.BusinessUpdateEnum": {
|
||||
"Change": "变化",
|
||||
"Interval": "定时",
|
||||
"IntervalOrChange": "定时或变化"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ConfigInfoController": {
|
||||
"ConfigInfoController": "获取配置信息",
|
||||
"GetChannelList": "获取通道信息",
|
||||
"GetCollectDeviceList": "获取设备信息",
|
||||
"GetVariableList": "获取变量信息"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ControlControler": {
|
||||
"ControlControler": "设备控制",
|
||||
"ThingsGateway.Gateway.Application.ControlController": {
|
||||
"ControlController": "设备控制",
|
||||
"PauseCollectThread": "控制采集线程启停",
|
||||
"PauseBusinessThread": "控制业务线程启停",
|
||||
"RestartCollectDeviceThread": "重启采集线程",
|
||||
"RestartBusinessDeviceThread": "重启业务线程",
|
||||
"WriteDeviceMethods": "写入变量"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.RuntimeInfoControler": {
|
||||
"RuntimeInfoControler": "获取运行态信息",
|
||||
"ThingsGateway.Gateway.Application.RuntimeInfoController": {
|
||||
"RuntimeInfoController": "获取运行态信息",
|
||||
"GetCollectDeviceList": "获取设备信息",
|
||||
"GetVariableList": "获取变量信息",
|
||||
"GetRealAlarmList": "获取实时报警信息",
|
||||
@@ -145,7 +148,7 @@
|
||||
"ReadExpressions": "读取表达式",
|
||||
"WriteExpressions": "写入表达式",
|
||||
"RpcWriteEnable": "远程写入",
|
||||
"SaveValue": "保存值",
|
||||
"SaveValue": "保存初始值",
|
||||
|
||||
"AlarmDelay": "报警延时",
|
||||
"BoolOpenAlarmEnable": "布尔开报警使能",
|
||||
@@ -422,7 +425,8 @@
|
||||
"ReadExpressions": "读取表达式",
|
||||
"WriteExpressions": "写入表达式",
|
||||
"RpcWriteEnable": "远程写入",
|
||||
"SaveValue": "保存值",
|
||||
"Value": "初始值",
|
||||
"SaveValue": "保存初始值",
|
||||
|
||||
"AlarmDelay": "报警延时",
|
||||
"BoolOpenAlarmEnable": "布尔开报警使能",
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
{
|
||||
|
||||
"ThingsGateway.Gateway.Application.ConfigInfoControler": {
|
||||
"ConfigInfoControler": "獲取配置資訊",
|
||||
"ThingsGateway.Gateway.Application.BusinessUpdateEnum": {
|
||||
"Change": "變化",
|
||||
"Interval": "定時",
|
||||
"IntervalOrChange": "定時或變化"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ConfigInfoController": {
|
||||
"ConfigInfoController": "獲取配置資訊",
|
||||
"GetChannelList": "獲取通道資訊",
|
||||
"GetCollectDeviceList": "獲取設備資訊",
|
||||
"GetVariableList": "獲取變量資訊"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.ControlControler": {
|
||||
"ControlControler": "設備控制",
|
||||
"ThingsGateway.Gateway.Application.ControlController": {
|
||||
"ControlController": "設備控制",
|
||||
"PauseCollectThread": "控制採集線程啟停",
|
||||
"PauseBusinessThread": "控制業務線程啟停",
|
||||
"RestartCollectDeviceThread": "重启採集線程",
|
||||
"RestartBusinessDeviceThread": "重启業務線程",
|
||||
"WriteDeviceMethods": "寫入變量"
|
||||
},
|
||||
"ThingsGateway.Gateway.Application.RuntimeInfoControler": {
|
||||
"RuntimeInfoControler": "獲取運行態信息",
|
||||
"ThingsGateway.Gateway.Application.RuntimeInfoController": {
|
||||
"RuntimeInfoController": "獲取運行態信息",
|
||||
"GetCollectDeviceList": "獲取設備信息",
|
||||
"GetVariableList": "獲取變量信息",
|
||||
"GetRealAlarmList": "獲取實時警報信息",
|
||||
@@ -131,7 +135,7 @@
|
||||
"ReadExpressions": "讀取表達式",
|
||||
"WriteExpressions": "寫入表達式",
|
||||
"RpcWriteEnable": "遠端寫入",
|
||||
"SaveValue": "保存值",
|
||||
"SaveValue": "保存初始值",
|
||||
"AlarmDelay": "警報延遲",
|
||||
"BoolOpenAlarmEnable": "布林開警報啟用",
|
||||
"BoolOpenRestrainExpressions": "布林開警報約束",
|
||||
@@ -386,7 +390,8 @@
|
||||
"ReadExpressions": "讀取表達式",
|
||||
"WriteExpressions": "寫入表達式",
|
||||
"RpcWriteEnable": "遠端寫入",
|
||||
"SaveValue": "保存值",
|
||||
"SaveValue": "保存初始值",
|
||||
"Value": "初始值",
|
||||
"AlarmDelay": "警報延遲",
|
||||
"BoolOpenAlarmEnable": "布林開警報啟用",
|
||||
"BoolOpenRestrainExpressions": "布林開警報約束",
|
||||
|
||||
@@ -24,9 +24,9 @@ public class VariableMethod
|
||||
|
||||
private object?[]? OS;
|
||||
|
||||
public VariableMethod(Method method, VariableRunTime variable, int milliSeconds = 1000)
|
||||
public VariableMethod(Method method, VariableRunTime variable, string delay)
|
||||
{
|
||||
_timeTick = new TimeTick(milliSeconds);
|
||||
_timeTick = new TimeTick(delay);
|
||||
MethodInfo = method;
|
||||
Variable = variable;
|
||||
variable.VariableMethod = this;
|
||||
|
||||
@@ -12,6 +12,7 @@ using BootstrapBlazor.Components;
|
||||
|
||||
using Mapster;
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using ThingsGateway.Core.Json.Extension;
|
||||
@@ -44,7 +45,7 @@ public class VariableRunTime : Variable, IVariable
|
||||
public override bool Enable { get; set; }
|
||||
|
||||
[AutoGenerateColumn(Visible = false, Filterable = true, Sortable = true)]
|
||||
public override int? IntervalTime { get; set; }
|
||||
public override string? IntervalTime { get; set; }
|
||||
|
||||
#endregion 重写
|
||||
|
||||
@@ -154,7 +155,7 @@ public class VariableRunTime : Variable, IVariable
|
||||
/// 实时值
|
||||
/// </summary>
|
||||
[AutoGenerateColumn(Visible = true, Order = 6)]
|
||||
public object? Value { get => _value; internal set => _value = value; }
|
||||
public override object? Value { get => _value; set => _value = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置变量值与时间/质量戳
|
||||
@@ -182,7 +183,15 @@ public class VariableRunTime : Variable, IVariable
|
||||
{
|
||||
IsOnline = false;
|
||||
Set(null, dateTime);
|
||||
lastErrorMessage = $"{Name} Conversion expression failed:{ex.Message}";
|
||||
if (ex.StackTrace != null)
|
||||
{
|
||||
string stachTrace = string.Join(Environment.NewLine, ex.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Take(3));
|
||||
lastErrorMessage = $"{Name} Conversion expression failed:{ex.Message}{Environment.NewLine}{stachTrace}";
|
||||
}
|
||||
else
|
||||
{
|
||||
lastErrorMessage = $"{Name} Conversion expression failed:{ex.Message}{Environment.NewLine}";
|
||||
}
|
||||
return new($"{Name} Conversion expression failed", ex);
|
||||
}
|
||||
}
|
||||
@@ -201,7 +210,10 @@ public class VariableRunTime : Variable, IVariable
|
||||
bool changed = false;
|
||||
if (data == null)
|
||||
{
|
||||
changed = (_value != null);
|
||||
if (IsOnline)
|
||||
{
|
||||
changed = (_value != null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -259,13 +271,13 @@ public class VariableRunTime : Variable, IVariable
|
||||
#region LoadSourceRead
|
||||
|
||||
/// <summary>
|
||||
/// 这个参数值由自动打包方法写入<see cref="IProtocol.LoadSourceRead{T}(IEnumerable{IVariable}, int, int)"/>
|
||||
/// 这个参数值由自动打包方法写入<see cref="IProtocol.LoadSourceRead{T}(IEnumerable{IVariable}, int, string)"/>
|
||||
/// </summary>
|
||||
[AutoGenerateColumn(Visible = false)]
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 这个参数值由自动打包方法写入<see cref="IProtocol.LoadSourceRead{T}(IEnumerable{IVariable}, int, int)"/>
|
||||
/// 这个参数值由自动打包方法写入<see cref="IProtocol.LoadSourceRead{T}(IEnumerable{IVariable}, int, string)"/>
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
|
||||
@@ -81,8 +81,11 @@ public abstract class BusinessBase : DriverBase
|
||||
CurrentDevice.RefreshBusinessDeviceRuntime(device.Id);
|
||||
|
||||
// 如果设备的采集间隔小于等于50毫秒,则将其设置为50毫秒
|
||||
if (device.IntervalTime <= 50)
|
||||
device.IntervalTime = 50;
|
||||
if (int.TryParse(device.IntervalTime, out int delay))
|
||||
{
|
||||
if (delay <= 50)
|
||||
device.IntervalTime = "50";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,7 +93,7 @@ public abstract class BusinessBase : DriverBase
|
||||
/// </summary>
|
||||
protected async Task Delay(CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Delay(Math.Max(CurrentDevice.IntervalTime - ChannelThread.CycleInterval, ChannelThread.CycleInterval), cancellationToken).ConfigureAwait(false);
|
||||
await Task.Delay(ChannelThread.CycleInterval, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -30,10 +30,15 @@ public abstract class BusinessBaseWithCacheAlarmModel<VarModel, DevModel, AlarmM
|
||||
/// <param name="data"></param>
|
||||
protected virtual void AddCache(List<CacheDBItem<AlarmModel>> data)
|
||||
{
|
||||
|
||||
if (_businessPropertyWithCache.CacheEnable && data?.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.Id = CommonUtils.GetSingleId();
|
||||
}
|
||||
var dir = CacheDBUtil.GetFilePath(CurrentDevice.Id.ToString());
|
||||
var fileStart = CacheDBUtil.GetFileName($"{CurrentDevice.PluginName}_{typeof(AlarmModel).FullName}_{nameof(AlarmModel)}");
|
||||
var fullName = dir.CombinePathWithOs($"{fileStart}{CacheDBUtil.EX}");
|
||||
|
||||
@@ -30,10 +30,16 @@ public abstract class BusinessBaseWithCacheDeviceModel<VarModel, DevModel> : Bus
|
||||
/// <param name="data"></param>
|
||||
protected virtual void AddCache(List<CacheDBItem<DevModel>> data)
|
||||
{
|
||||
|
||||
if (_businessPropertyWithCache.CacheEnable && data?.Count > 0)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.Id = CommonUtils.GetSingleId();
|
||||
}
|
||||
var dir = CacheDBUtil.GetFilePath(CurrentDevice.Id.ToString());
|
||||
var fileStart = CacheDBUtil.GetFileName($"{CurrentDevice.PluginName}_{typeof(DevModel).FullName}_{nameof(DevModel)}");
|
||||
var fullName = dir.CombinePathWithOs($"{fileStart}{CacheDBUtil.EX}");
|
||||
|
||||
@@ -38,6 +38,10 @@ public abstract class BusinessBaseWithCacheVariableModel<VarModel> : BusinessBas
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.Id = CommonUtils.GetSingleId();
|
||||
}
|
||||
var dir = CacheDBUtil.GetFilePath(CurrentDevice.Id.ToString());
|
||||
var fileStart = CacheDBUtil.GetFileName($"{CurrentDevice.PluginName}_{typeof(VarModel).FullName}_{nameof(VarModel)}");
|
||||
var fullName = dir.CombinePathWithOs($"{fileStart}{CacheDBUtil.EX}");
|
||||
|
||||
@@ -45,8 +45,11 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
}
|
||||
|
||||
// 如果业务属性的缓存要求的业务间隔小于等于100,则设置为100
|
||||
if (_businessPropertyWithCacheInterval.BusinessInterval <= 100)
|
||||
_businessPropertyWithCacheInterval.BusinessInterval = 100;
|
||||
if (int.TryParse(_businessPropertyWithCacheInterval.BusinessInterval, out int delay))
|
||||
{
|
||||
if (delay <= 100)
|
||||
_businessPropertyWithCacheInterval.BusinessInterval = "100";
|
||||
}
|
||||
|
||||
// 初始化
|
||||
_exTTimerTick = new(_businessPropertyWithCacheInterval.BusinessInterval);
|
||||
@@ -54,30 +57,30 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
|
||||
GlobalData.AlarmHostedService.OnAlarmChanged -= AlarmValueChange;
|
||||
GlobalData.AlarmHostedService.OnAlarmChanged += AlarmValueChange;
|
||||
// 解绑全局数据的事件
|
||||
GlobalData.VariableValueChangeEvent -= VariableValueChange;
|
||||
GlobalData.DeviceStatusChangeEvent -= DeviceStatusChange;
|
||||
|
||||
// 根据业务属性的缓存是否为间隔上传来决定事件绑定
|
||||
if (!_businessPropertyWithCacheInterval.IsInterval)
|
||||
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
{
|
||||
// 解绑全局数据的事件
|
||||
GlobalData.VariableValueChangeEvent -= VariableValueChange;
|
||||
GlobalData.DeviceStatusChangeEvent -= DeviceStatusChange;
|
||||
|
||||
// 绑定全局数据的事件
|
||||
GlobalData.DeviceStatusChangeEvent += DeviceStatusChange;
|
||||
GlobalData.VariableValueChangeEvent += VariableValueChange;
|
||||
|
||||
// 触发一次设备状态变化和变量值变化事件
|
||||
CollectDevices.ForEach(a =>
|
||||
{
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine)
|
||||
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
|
||||
});
|
||||
CurrentDevice.VariableRunTimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
||||
// 触发一次设备状态变化和变量值变化事件
|
||||
CollectDevices.ForEach(a =>
|
||||
{
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine)
|
||||
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
|
||||
});
|
||||
CurrentDevice.VariableRunTimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -98,7 +101,15 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
{
|
||||
// 在设备状态变化时执行的自定义逻辑
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当设备状态定时变化时触发此方法。如果不需要进行设备上传,则可以忽略此方法。通常情况下,需要在此方法中执行 <see cref="BusinessBaseWithCacheDeviceModel{T,T2}.AddQueueDevModel(CacheDBItem{T2})"/> 方法。
|
||||
/// </summary>
|
||||
/// <param name="deviceRunTime">设备运行时信息</param>
|
||||
/// <param name="deviceData">设备数据</param>
|
||||
protected virtual void DeviceTimeInterval(DeviceRunTime deviceRunTime, DeviceBasicData deviceData)
|
||||
{
|
||||
// 在设备状态变化时执行的自定义逻辑
|
||||
}
|
||||
/// <summary>
|
||||
/// 释放资源方法
|
||||
/// </summary>
|
||||
@@ -121,6 +132,8 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
/// </summary>
|
||||
protected virtual async Task IntervalInsert()
|
||||
{
|
||||
var vardatas = CurrentDevice.VariableRunTimes.Values.ToList();
|
||||
var devdatas = CollectDevices.Values.ToList();
|
||||
while (!DisposedValue)
|
||||
{
|
||||
if (CurrentDevice?.KeepRun == false)
|
||||
@@ -130,16 +143,16 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
}
|
||||
|
||||
// 如果业务属性的缓存为间隔上传,则根据定时器间隔执行相应操作
|
||||
if (_businessPropertyWithCacheInterval.IsInterval)
|
||||
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Change)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
// 间隔推送全部变量
|
||||
foreach (var variableRuntime in CurrentDevice.VariableRunTimes)
|
||||
foreach (var variableRuntime in vardatas)
|
||||
{
|
||||
VariableChange(variableRuntime.Value, variableRuntime.Value.Adapt<VariableBasicData>());
|
||||
VariableTimeInterval(variableRuntime, variableRuntime.Adapt<VariableBasicData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,9 +165,9 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
if (_exT2TimerTick.IsTickHappen())
|
||||
{
|
||||
// 间隔推送全部设备
|
||||
foreach (var deviceRuntime in CollectDevices)
|
||||
foreach (var deviceRuntime in devdatas)
|
||||
{
|
||||
DeviceChange(deviceRuntime.Value, deviceRuntime.Value.Adapt<DeviceBasicData>());
|
||||
DeviceTimeInterval(deviceRuntime, deviceRuntime.Adapt<DeviceBasicData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +200,15 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
{
|
||||
// 在变量状态变化时执行的自定义逻辑
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当变量定时变化时触发此方法。如果不需要进行变量上传,则可以忽略此方法。通常情况下,需要在此方法中执行 <see cref="BusinessBaseWithCacheVariableModel{T}.AddQueueVarModel(CacheDBItem{T})"/> 方法。
|
||||
/// </summary>
|
||||
/// <param name="variableRunTime">变量运行时信息</param>
|
||||
/// <param name="variable">变量数据</param>
|
||||
protected virtual void VariableTimeInterval(VariableRunTime variableRunTime, VariableBasicData variable)
|
||||
{
|
||||
// 在变量状态变化时执行的自定义逻辑
|
||||
}
|
||||
/// <summary>
|
||||
/// 当报警值发生变化时触发此事件处理方法。该方法内部会检查是否需要进行报警上传,如果需要,则调用 <see cref="AlarmChange(AlarmVariable)"/> 方法。
|
||||
/// </summary>
|
||||
@@ -197,7 +218,7 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
if (!CurrentDevice.KeepRun)
|
||||
return;
|
||||
// 如果业务属性的缓存为间隔上传,则不执行后续操作
|
||||
if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
//if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
{
|
||||
// 检查当前设备的变量是否包含此报警变量,如果包含,则触发报警变量的变化处理方法
|
||||
if (CurrentDevice.VariableRunTimes.ContainsKey(alarmVariable.Name))
|
||||
@@ -215,7 +236,7 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
if (!CurrentDevice.KeepRun)
|
||||
return;
|
||||
// 如果业务属性的缓存为间隔上传,则不执行后续操作
|
||||
if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
//if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
{
|
||||
// 检查当前设备的设备列表是否包含此设备,如果包含,则触发设备的状态变化处理方法
|
||||
if (CollectDevices.ContainsKey(deviceData.Name))
|
||||
@@ -233,7 +254,7 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
|
||||
if (!CurrentDevice.KeepRun)
|
||||
return;
|
||||
// 如果业务属性的缓存为间隔上传,则不执行后续操作
|
||||
if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
//if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
{
|
||||
// 检查当前设备的变量是否包含此变量,如果包含,则触发变量的变化处理方法
|
||||
if (CurrentDevice.VariableRunTimes.ContainsKey(variable.Name))
|
||||
|
||||
@@ -51,8 +51,11 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
}
|
||||
|
||||
// 设置业务间隔时间的最小值为100毫秒
|
||||
if (_businessPropertyWithCacheInterval.BusinessInterval <= 100)
|
||||
_businessPropertyWithCacheInterval.BusinessInterval = 100;
|
||||
if (int.TryParse(_businessPropertyWithCacheInterval.BusinessInterval, out int delay))
|
||||
{
|
||||
if (delay <= 100)
|
||||
_businessPropertyWithCacheInterval.BusinessInterval = "100";
|
||||
}
|
||||
|
||||
// 初始化设备和变量上传的定时器
|
||||
_exTTimerTick = new(_businessPropertyWithCacheInterval.BusinessInterval);
|
||||
@@ -63,21 +66,22 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
GlobalData.DeviceStatusChangeEvent -= DeviceStatusChange;
|
||||
|
||||
// 如果不是间隔上传,则订阅全局变量值改变事件和设备状态改变事件,并触发一次事件处理
|
||||
if (!_businessPropertyWithCacheInterval.IsInterval)
|
||||
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
{
|
||||
GlobalData.DeviceStatusChangeEvent += DeviceStatusChange;
|
||||
GlobalData.VariableValueChangeEvent += VariableValueChange;
|
||||
CollectDevices.ForEach(a =>
|
||||
{
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine)
|
||||
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
|
||||
});
|
||||
CurrentDevice.VariableRunTimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
|
||||
}
|
||||
CollectDevices.ForEach(a =>
|
||||
{
|
||||
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine)
|
||||
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
|
||||
});
|
||||
CurrentDevice.VariableRunTimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,7 +92,15 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
protected virtual void DeviceChange(DeviceRunTime deviceRunTime, DeviceBasicData deviceData)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当设备状态定时变化时触发此方法。如果不需要进行设备上传,则可以忽略此方法。通常情况下,需要在此方法中执行 <see cref="BusinessBaseWithCacheDeviceModel{T,T2}.AddQueueDevModel(CacheDBItem{T2})"/> 方法。
|
||||
/// </summary>
|
||||
/// <param name="deviceRunTime">设备运行时信息</param>
|
||||
/// <param name="deviceData">设备数据</param>
|
||||
protected virtual void DeviceTimeInterval(DeviceRunTime deviceRunTime, DeviceBasicData deviceData)
|
||||
{
|
||||
// 在设备状态变化时执行的自定义逻辑
|
||||
}
|
||||
/// <summary>
|
||||
/// 释放资源的方法,释放插件相关资源。
|
||||
/// </summary>
|
||||
@@ -111,6 +123,8 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
/// <returns>异步任务</returns>
|
||||
protected virtual async Task IntervalInsert()
|
||||
{
|
||||
var vardatas = CurrentDevice.VariableRunTimes.Values.ToList();
|
||||
var devdatas = CollectDevices.Values.ToList();
|
||||
while (!DisposedValue)
|
||||
{
|
||||
if (CurrentDevice?.KeepRun == false)
|
||||
@@ -120,16 +134,16 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
}
|
||||
|
||||
// 如果是间隔上传,根据定时器触发事件上传设备和变量信息
|
||||
if (_businessPropertyWithCacheInterval.IsInterval)
|
||||
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Change)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
// 上传所有变量信息
|
||||
foreach (var variableRuntime in CurrentDevice.VariableRunTimes)
|
||||
foreach (var variableRuntime in vardatas)
|
||||
{
|
||||
VariableChange(variableRuntime.Value, variableRuntime.Value.Adapt<VariableData>());
|
||||
VariableTimeInterval(variableRuntime, variableRuntime.Adapt<VariableBasicData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,9 +157,9 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
if (_exT2TimerTick.IsTickHappen())
|
||||
{
|
||||
// 上传所有设备信息
|
||||
foreach (var deviceRuntime in CollectDevices)
|
||||
foreach (var deviceRuntime in devdatas)
|
||||
{
|
||||
DeviceChange(deviceRuntime.Value, deviceRuntime.Value.Adapt<DeviceBasicData>());
|
||||
DeviceTimeInterval(deviceRuntime, deviceRuntime.Adapt<DeviceBasicData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +192,15 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
protected virtual void VariableChange(VariableRunTime variableRunTime, VariableData variable)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当变量定时变化时触发此方法。如果不需要进行变量上传,则可以忽略此方法。通常情况下,需要在此方法中执行 <see cref="BusinessBaseWithCacheVariableModel{T}.AddQueueVarModel(CacheDBItem{T})"/> 方法。
|
||||
/// </summary>
|
||||
/// <param name="variableRunTime">变量运行时信息</param>
|
||||
/// <param name="variable">变量数据</param>
|
||||
protected virtual void VariableTimeInterval(VariableRunTime variableRunTime, VariableBasicData variable)
|
||||
{
|
||||
// 在变量状态变化时执行的自定义逻辑
|
||||
}
|
||||
/// <summary>
|
||||
/// 设备状态改变时的事件处理方法。
|
||||
/// </summary>
|
||||
@@ -191,7 +213,7 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
return;
|
||||
|
||||
// 如果业务属性不是间隔上传,则执行设备状态改变的处理逻辑
|
||||
if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
//if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
{
|
||||
// 检查当前设备集合中是否包含该设备,并进行相应处理
|
||||
if (CollectDevices.ContainsKey(deviceRunTime.Name))
|
||||
@@ -211,7 +233,7 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
|
||||
return;
|
||||
|
||||
// 如果业务属性不是间隔上传,则执行变量状态改变的处理逻辑
|
||||
if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
//if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
{
|
||||
// 检查当前设备是否包含该变量,并进行相应处理
|
||||
if (CurrentDevice.VariableRunTimes.ContainsKey(variableRunTime.Name))
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ThingsGateway.Core.Json.Extension;
|
||||
|
||||
using TouchSocket.Core;
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
/// <summary>
|
||||
@@ -57,6 +61,84 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
}
|
||||
|
||||
#region 封装方法
|
||||
protected List<TopicArray> GetAlarmTopicArrays(IEnumerable<AlarmModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<AlarmModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptAlarmModel);
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.AlarmTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
{
|
||||
//获取分组最终结果
|
||||
var groups = data.GroupByKeys(topics);
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
// 上传主题
|
||||
// 获取预定义的报警主题
|
||||
string topic = _businessPropertyWithCacheIntervalScript.AlarmTopic;
|
||||
|
||||
// 将主题中的占位符替换为分组键对应的值
|
||||
for (int i = 0; i < topics.Count; i++)
|
||||
{
|
||||
topic = topic.Replace(@"${" + topics[i] + @"}", group.Key[i]?.ToString());
|
||||
}
|
||||
|
||||
// 上传内容
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
var json = Serialize(group.Select(a => a).ToList().ToList());
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果不是报警列表,则将每个分组元素分别转换为 JSON 字符串
|
||||
foreach (var gro in group)
|
||||
{
|
||||
var json = Serialize(gro);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList());
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return topicJsonList;
|
||||
}
|
||||
|
||||
protected static ArraySegment<byte> Serialize(object value)
|
||||
{
|
||||
var block = new ValueByteBlock(1024 * 64);
|
||||
try
|
||||
{
|
||||
//将数据序列化到内存块
|
||||
FastBinaryFormatter.Serialize(ref block, value);
|
||||
block.SeekToStart();
|
||||
return block.Memory.GetArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
block.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected List<TopicJson> GetAlarms(IEnumerable<AlarmModel> item)
|
||||
{
|
||||
@@ -85,7 +167,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
// 如果是报警列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).ToJsonNetString();
|
||||
string json = group.Select(a => a).ToList().ToJsonNetString();
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
@@ -106,7 +188,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsAlarmList)
|
||||
{
|
||||
string json = data.Select(a => a).ToJsonNetString();
|
||||
string json = data.Select(a => a).ToList().ToJsonNetString();
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.AlarmTopic, json));
|
||||
}
|
||||
else
|
||||
@@ -150,7 +232,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
// 如果是设备列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).ToJsonNetString();
|
||||
string json = group.Select(a => a).ToList().ToJsonNetString();
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
@@ -172,7 +254,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
string json = data.Select(a => a).ToJsonNetString();
|
||||
string json = data.Select(a => a).ToList().ToJsonNetString();
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
}
|
||||
else
|
||||
@@ -187,6 +269,71 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
return topicJsonList;
|
||||
}
|
||||
|
||||
protected List<TopicArray> GetDeviceTopicArray(IEnumerable<DevModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<DevModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptDeviceModel);
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.DeviceTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
{
|
||||
//获取分组最终结果
|
||||
var groups = data.GroupByKeys(topics).ToList();
|
||||
if (groups.Count > 0)
|
||||
{
|
||||
foreach (var group in groups)
|
||||
{
|
||||
// 上传主题
|
||||
// 获取预定义的设备主题
|
||||
string topic = _businessPropertyWithCacheIntervalScript.DeviceTopic;
|
||||
|
||||
// 将主题中的占位符替换为分组键对应的值
|
||||
for (int i = 0; i < topics.Count; i++)
|
||||
{
|
||||
topic = topic.Replace(@"${" + topics[i] + @"}", group.Key[i]?.ToString());
|
||||
}
|
||||
|
||||
// 上传内容
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
// 如果是设备列表,则将整个分组转换为 JSON 字符串
|
||||
var json = Serialize(group.Select(a => a).ToList());
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果不是设备列表,则将每个分组元素分别转换为 JSON 字符串
|
||||
foreach (var gro in group)
|
||||
{
|
||||
var json = Serialize(gro);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsDeviceList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList());
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.DeviceTopic, json));
|
||||
}
|
||||
}
|
||||
}
|
||||
return topicJsonList;
|
||||
}
|
||||
|
||||
protected List<TopicJson> GetVariable(IEnumerable<VarModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<VarModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptVariableModel);
|
||||
@@ -215,7 +362,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
// 如果是变量列表,则将整个分组转换为 JSON 字符串
|
||||
string json = group.Select(a => a).ToJsonNetString();
|
||||
string json = group.Select(a => a).ToList().ToJsonNetString();
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
@@ -237,7 +384,7 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
string json = data.Select(a => a).ToJsonNetString();
|
||||
string json = data.Select(a => a).ToList().ToJsonNetString();
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
}
|
||||
else
|
||||
@@ -252,5 +399,71 @@ public abstract partial class BusinessBaseWithCacheIntervalScript<VarModel, DevM
|
||||
return topicJsonList;
|
||||
}
|
||||
|
||||
|
||||
protected List<TopicArray> GetVariableTopicArray(IEnumerable<VarModel> item)
|
||||
{
|
||||
IEnumerable<dynamic>? data = Application.DynamicModelExtension.GetDynamicModel<VarModel>(item, _businessPropertyWithCacheIntervalScript.BigTextScriptVariableModel);
|
||||
List<TopicArray> topicJsonList = new List<TopicArray>();
|
||||
var topics = Match(_businessPropertyWithCacheIntervalScript.VariableTopic);
|
||||
if (topics.Count > 0)
|
||||
{
|
||||
{
|
||||
//获取分组最终结果
|
||||
var groups = data.GroupByKeys(topics).ToList();
|
||||
if (groups.Count > 0)
|
||||
{
|
||||
foreach (var group in groups)
|
||||
{
|
||||
// 上传主题
|
||||
// 获取预定义的变量主题
|
||||
string topic = _businessPropertyWithCacheIntervalScript.VariableTopic;
|
||||
|
||||
// 将主题中的占位符替换为分组键对应的值
|
||||
for (int i = 0; i < topics.Count; i++)
|
||||
{
|
||||
topic = topic.Replace(@"${" + topics[i] + @"}", group.Key[i]?.ToString());
|
||||
}
|
||||
|
||||
// 上传内容
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
// 如果是变量列表,则将整个分组转换为 JSON 字符串
|
||||
var json = Serialize(group.Select(a => a).ToList());
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果不是变量列表,则将每个分组元素分别转换为 JSON 字符串
|
||||
foreach (var gro in group)
|
||||
{
|
||||
var json = Serialize(gro);
|
||||
// 将主题和 JSON 内容添加到列表中
|
||||
topicJsonList.Add(new(topic, json));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_businessPropertyWithCacheIntervalScript.IsVariableList)
|
||||
{
|
||||
var json = Serialize(data.Select(a => a).ToList());
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var group in data)
|
||||
{
|
||||
var json = Serialize(group);
|
||||
topicJsonList.Add(new(_businessPropertyWithCacheIntervalScript.VariableTopic, json));
|
||||
}
|
||||
}
|
||||
}
|
||||
return topicJsonList;
|
||||
}
|
||||
|
||||
#endregion 封装方法
|
||||
}
|
||||
|
||||
@@ -49,24 +49,28 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBa
|
||||
}
|
||||
|
||||
// 如果业务间隔小于等于100毫秒,则将业务间隔设置为100毫秒
|
||||
if (_businessPropertyWithCacheInterval.BusinessInterval <= 100)
|
||||
_businessPropertyWithCacheInterval.BusinessInterval = 100;
|
||||
if (int.TryParse(_businessPropertyWithCacheInterval.BusinessInterval, out int delay))
|
||||
{
|
||||
if (delay <= 100)
|
||||
_businessPropertyWithCacheInterval.BusinessInterval = "100";
|
||||
}
|
||||
|
||||
// 初始化定时器
|
||||
_exTTimerTick = new TimeTick(_businessPropertyWithCacheInterval.BusinessInterval);
|
||||
|
||||
// 注册变量值变化事件处理程序
|
||||
GlobalData.VariableValueChangeEvent -= VariableValueChange;
|
||||
if (!_businessPropertyWithCacheInterval.IsInterval)
|
||||
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
|
||||
{
|
||||
GlobalData.VariableValueChangeEvent += VariableValueChange;
|
||||
// 触发一次变量值变化事件
|
||||
CurrentDevice.VariableRunTimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableData>());
|
||||
});
|
||||
|
||||
}
|
||||
// 触发一次变量值变化事件
|
||||
CurrentDevice.VariableRunTimes.ForEach(a =>
|
||||
{
|
||||
if (a.Value.IsOnline)
|
||||
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -86,6 +90,7 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBa
|
||||
/// <returns>表示异步操作的任务</returns>
|
||||
protected virtual async Task IntervalInsert()
|
||||
{
|
||||
var vardatas = CurrentDevice.VariableRunTimes.Values.ToList();
|
||||
while (!DisposedValue)
|
||||
{
|
||||
if (CurrentDevice?.KeepRun == false)
|
||||
@@ -94,36 +99,31 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBa
|
||||
continue;
|
||||
}
|
||||
//间隔上传
|
||||
IntervalInsertVariable();
|
||||
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Change)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
//间隔推送全部变量
|
||||
foreach (var variableRuntime in vardatas)
|
||||
{
|
||||
VariableTimeInterval(variableRuntime, variableRuntime.Adapt<VariableBasicData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.LogWarning(ex, BusinessBaseLocalizer["IntervalInsertVariableFail"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await Delay(default).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔插入变量的操作。
|
||||
/// </summary>
|
||||
protected virtual void IntervalInsertVariable()
|
||||
{
|
||||
if (_businessPropertyWithCacheInterval.IsInterval)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_exTTimerTick.IsTickHappen())
|
||||
{
|
||||
//间隔推送全部变量
|
||||
foreach (var variableRuntime in CurrentDevice.VariableRunTimes)
|
||||
{
|
||||
VariableChange(variableRuntime.Value, variableRuntime.Value.Adapt<VariableData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.LogWarning(ex, BusinessBaseLocalizer["IntervalInsertVariableFail"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 在启动前执行的异步操作。
|
||||
@@ -142,20 +142,28 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<T> : BusinessBa
|
||||
/// </summary>
|
||||
/// <param name="variableRunTime">变量运行时对象</param>
|
||||
/// <param name="variable">变量运行时对象</param>
|
||||
protected virtual void VariableChange(VariableRunTime variableRunTime, VariableData variable)
|
||||
protected virtual void VariableChange(VariableRunTime variableRunTime, VariableBasicData variable)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当变量定时变化时触发此方法。如果不需要进行变量上传,则可以忽略此方法。通常情况下,需要在此方法中执行 <see cref="BusinessBaseWithCacheVariableModel{T}.AddQueueVarModel(CacheDBItem{T})"/> 方法。
|
||||
/// </summary>
|
||||
/// <param name="variableRunTime">变量运行时信息</param>
|
||||
/// <param name="variable">变量数据</param>
|
||||
protected virtual void VariableTimeInterval(VariableRunTime variableRunTime, VariableBasicData variable)
|
||||
{
|
||||
// 在变量状态变化时执行的自定义逻辑
|
||||
}
|
||||
/// <summary>
|
||||
/// 当变量值发生变化时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="variableRunTime">变量运行时对象</param>
|
||||
/// <param name="variable">变量数据</param>
|
||||
private void VariableValueChange(VariableRunTime variableRunTime, VariableData variable)
|
||||
private void VariableValueChange(VariableRunTime variableRunTime, VariableBasicData variable)
|
||||
{
|
||||
if (!CurrentDevice.KeepRun)
|
||||
return;
|
||||
if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
//if (_businessPropertyWithCacheInterval?.IsInterval != true)
|
||||
{
|
||||
//筛选
|
||||
if (CurrentDevice.VariableRunTimes.ContainsKey(variableRunTime.Name))
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
public enum BusinessUpdateEnum
|
||||
{
|
||||
Change,
|
||||
Interval,
|
||||
IntervalOrChange,
|
||||
}
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
@@ -19,14 +25,14 @@ public class BusinessPropertyWithCacheInterval : BusinessPropertyWithCache
|
||||
public virtual bool IsAllVariable { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否间隔上传
|
||||
/// 上传模式
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual bool IsInterval { get; set; } = false;
|
||||
public virtual BusinessUpdateEnum BusinessUpdateEnum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 间隔上传时间
|
||||
/// </summary>
|
||||
[DynamicProperty]
|
||||
public virtual int BusinessInterval { get; set; } = 1000;
|
||||
public virtual string BusinessInterval { get; set; } = "1000";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://thingsgateway.cn/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
|
||||
public struct TopicArray
|
||||
{
|
||||
public TopicArray(string topic, ArraySegment<byte> json)
|
||||
{
|
||||
Topic = topic; Json = json;
|
||||
}
|
||||
|
||||
public ArraySegment<byte> Json { get; set; }
|
||||
public string Topic { get; set; }
|
||||
}
|
||||
@@ -19,12 +19,10 @@ public class CacheDBItem<T> : IPrimaryIdEntity
|
||||
{
|
||||
public CacheDBItem()
|
||||
{
|
||||
Id = CommonUtils.GetSingleId();
|
||||
}
|
||||
|
||||
public CacheDBItem(T value)
|
||||
{
|
||||
Id = CommonUtils.GetSingleId();
|
||||
Value = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,7 @@ using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
using ThingsGateway.NewLife.Extension;
|
||||
|
||||
@@ -112,9 +109,11 @@ public class ChannelThread
|
||||
/// <summary>
|
||||
/// 通道线程构造函数,用于初始化通道线程实例。
|
||||
/// </summary>
|
||||
/// <param name="channel">通道实例</param>
|
||||
/// <param name="getChannel">获取通道的方法</param>
|
||||
public ChannelThread(Channel channel, Func<TouchSocketConfig, IChannel> getChannel)
|
||||
/// <param name="channel">通道表</param>
|
||||
/// <param name="foundataionConfig">通道设置实例</param>
|
||||
/// <param name="ichannel">通道实例</param>
|
||||
/// <param name="loggerGroup">日志</param>
|
||||
public ChannelThread(Channel channel, TouchSocketConfig foundataionConfig, IChannel ichannel, LoggerGroup loggerGroup)
|
||||
{
|
||||
Localizer = App.CreateLocalizerByType(typeof(ChannelThread))!;
|
||||
// 初始化日志记录器,使用通道名称作为日志记录器的名称
|
||||
@@ -125,19 +124,14 @@ public class ChannelThread
|
||||
ChannelId = channel.Id;
|
||||
|
||||
// 初始化底层配置
|
||||
LogMessage = new LoggerGroup() { LogLevel = TouchSocket.Core.LogLevel.Warning };
|
||||
LogMessage = loggerGroup;
|
||||
|
||||
// 添加默认日志记录器
|
||||
LogMessage.AddLogger(new EasyLogger(Log_Out) { LogLevel = TouchSocket.Core.LogLevel.Trace });
|
||||
|
||||
// 初始化基础配置容器
|
||||
var foundataionConfig = new TouchSocketConfig();
|
||||
|
||||
// 配置容器中注册日志记录器实例
|
||||
foundataionConfig.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
|
||||
// 根据配置获取通道实例
|
||||
Channel = getChannel(foundataionConfig);
|
||||
Channel = ichannel;
|
||||
|
||||
// 设置日志路径为通道ID对应的日志路径
|
||||
LogPath = channel.Id.GetLogPath();
|
||||
@@ -366,21 +360,12 @@ public class ChannelThread
|
||||
try
|
||||
{
|
||||
//添加保存数据变量读取操作
|
||||
var saveVariable = driverBase.CurrentDevice.VariableRunTimes.Where(a => a.Value.SaveValue).Select(a =>
|
||||
{
|
||||
return new CacheDBItem<JToken>()
|
||||
{
|
||||
Id = a.Value.Id,
|
||||
Value = JToken.FromObject(a.Value.Value)
|
||||
};
|
||||
}).ToList();
|
||||
var saveVariable = driverBase.CurrentDevice.VariableRunTimes.Where(a => a.Value.SaveValue).Select(a => (Variable)a.Value).ToList();
|
||||
|
||||
if (saveVariable.Count > 0)
|
||||
{
|
||||
var cacheDb = CacheDBUtil.GetCache(typeof(CacheDBItem<JToken>), nameof(VariableRunTime), nameof(VariableRunTime.SaveValue));
|
||||
var varList = await cacheDb.DBProvider.Storageable(saveVariable).ExecuteCommandAsync().ConfigureAwait(false);
|
||||
|
||||
cacheDb.SafeDispose();
|
||||
using var db = DbContext.Db.GetConnectionScopeWithAttr<Variable>().CopyNew();
|
||||
var result = await db.Updateable<Variable>(saveVariable).UpdateColumns(a => a.Value).ExecuteCommandAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -475,7 +460,10 @@ public class ChannelThread
|
||||
driver?.ConfigurePlugins();
|
||||
}
|
||||
// 设置通道的底层配置
|
||||
Channel?.Setup(FoundataionConfig?.Clone());
|
||||
if (Channel != null)
|
||||
{
|
||||
await Channel.SetupAsync(FoundataionConfig?.Clone()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -70,7 +70,8 @@ public abstract class CollectBase : DriverBase
|
||||
Func<VariableRunTime, bool> source = (a =>
|
||||
{
|
||||
return a.RegisterAddress != nameof(DeviceRunTime.DeviceStatus) &&
|
||||
a.RegisterAddress != "Script"
|
||||
a.RegisterAddress != "Script" &&
|
||||
a.RegisterAddress != "ScriptRead"
|
||||
;
|
||||
|
||||
});
|
||||
@@ -125,7 +126,7 @@ public abstract class CollectBase : DriverBase
|
||||
if (method != null)
|
||||
{
|
||||
// 构建 VariableMethod 对象
|
||||
var methodResult = new VariableMethod(new Method(method.MethodInfo), item, item.IntervalTime ?? item.CollectDeviceRunTime.IntervalTime);
|
||||
var methodResult = new VariableMethod(new Method(method.MethodInfo), item, string.IsNullOrWhiteSpace(item.IntervalTime) ? item.CollectDeviceRunTime.IntervalTime : item.IntervalTime);
|
||||
variablesMethodResult.Add(methodResult);
|
||||
}
|
||||
else
|
||||
@@ -176,70 +177,77 @@ public abstract class CollectBase : DriverBase
|
||||
/// <returns></returns>
|
||||
protected override async ValueTask ProtectedExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
ReadResultCount readResultCount = new();
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (await TestOnline(cancellationToken).ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
if (CollectProperties.ConcurrentCount > 1)
|
||||
try
|
||||
{
|
||||
// 并行处理每个变量读取
|
||||
await CurrentDevice.VariableSourceReads.ParallelForEachAsync(async (variableSourceRead, cancellationToken) =>
|
||||
|
||||
ReadResultCount readResultCount = new();
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (await TestOnline(cancellationToken).ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
if (CollectProperties.ConcurrentCount > 1)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (await ReadVariableSource(readResultCount, variableSourceRead, cancellationToken, false).ConfigureAwait(false))
|
||||
return;
|
||||
// 并行处理每个变量读取
|
||||
await CurrentDevice.VariableSourceReads.ParallelForEachAsync(async (variableSourceRead, cancellationToken) =>
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (await ReadVariableSource(readResultCount, variableSourceRead, cancellationToken, false).ConfigureAwait(false))
|
||||
return;
|
||||
}
|
||||
, CollectProperties.ConcurrentCount, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < CurrentDevice.VariableSourceReads.Count; i++)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
// 每10包延迟一次
|
||||
if (await ReadVariableSource(readResultCount, CurrentDevice.VariableSourceReads[i], cancellationToken, i % 10 == 9).ConfigureAwait(false))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectProperties.ConcurrentCount > 1)
|
||||
{
|
||||
// 并行处理每个方法调用
|
||||
await CurrentDevice.ReadVariableMethods.ParallelForEachAsync(async (readVariableMethods, cancellationToken) =>
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (await ReadVariableMed(readResultCount, readVariableMethods, cancellationToken, false).ConfigureAwait(false))
|
||||
return;
|
||||
}
|
||||
, CollectProperties.ConcurrentCount, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < CurrentDevice.VariableSourceReads.Count; i++)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
// 每10包延迟一次
|
||||
if (await ReadVariableSource(readResultCount, CurrentDevice.VariableSourceReads[i], cancellationToken, i % 10 == 9).ConfigureAwait(false))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectProperties.ConcurrentCount > 1)
|
||||
{
|
||||
// 并行处理每个方法调用
|
||||
await CurrentDevice.ReadVariableMethods.ParallelForEachAsync(async (readVariableMethods, cancellationToken) =>
|
||||
else
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (await ReadVariableMed(readResultCount, readVariableMethods, cancellationToken, false).ConfigureAwait(false))
|
||||
return;
|
||||
for (int i = 0; i < CurrentDevice.ReadVariableMethods.Count; i++)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
// 每10包延迟一次
|
||||
if (await ReadVariableMed(readResultCount, CurrentDevice.ReadVariableMethods[i], cancellationToken, i % 10 == 9).ConfigureAwait(false))
|
||||
return;
|
||||
}
|
||||
}
|
||||
, CollectProperties.ConcurrentCount, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < CurrentDevice.ReadVariableMethods.Count; i++)
|
||||
|
||||
// 如果所有方法和变量读取都成功,则清零错误计数器
|
||||
if (readResultCount.deviceMethodsVariableFailedNum == 0 && readResultCount.deviceSourceVariableFailedNum == 0 && (readResultCount.deviceMethodsVariableSuccessNum != 0 || readResultCount.deviceSourceVariableSuccessNum != 0))
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
// 每10包延迟一次
|
||||
if (await ReadVariableMed(readResultCount, CurrentDevice.ReadVariableMethods[i], cancellationToken, i % 10 == 9).ConfigureAwait(false))
|
||||
return;
|
||||
//只有成功读取一次,失败次数都会清零
|
||||
CurrentDevice.SetDeviceStatus(TimerX.Now, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有方法和变量读取都成功,则清零错误计数器
|
||||
if (readResultCount.deviceMethodsVariableFailedNum == 0 && readResultCount.deviceSourceVariableFailedNum == 0 && (readResultCount.deviceMethodsVariableSuccessNum != 0 || readResultCount.deviceSourceVariableSuccessNum != 0))
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//只有成功读取一次,失败次数都会清零
|
||||
CurrentDevice.SetDeviceStatus(TimerX.Now, 0);
|
||||
ScriptVariableRun(cancellationToken);
|
||||
}
|
||||
|
||||
ScriptVariableRun(cancellationToken);
|
||||
|
||||
|
||||
#region 执行方法
|
||||
|
||||
async ValueTask<bool> ReadVariableMed(ReadResultCount readResultCount, VariableMethod readVariableMethods, CancellationToken cancellationToken, bool delay = true)
|
||||
@@ -473,7 +481,7 @@ public abstract class CollectBase : DriverBase
|
||||
{
|
||||
variableRunTime.SetValue(variableRunTime.CollectDeviceRunTime.DeviceStatus, dateTime);
|
||||
}
|
||||
else
|
||||
else if (variableRunTime.RegisterAddress == "ScriptRead")
|
||||
{
|
||||
variableRunTime.SetValue(default, dateTime);
|
||||
}
|
||||
@@ -667,6 +675,7 @@ public abstract class CollectBase : DriverBase
|
||||
// 初始化结果字典
|
||||
Dictionary<string, OperResult> results = new Dictionary<string, OperResult>();
|
||||
|
||||
|
||||
// 遍历写入信息列表
|
||||
foreach (var (deviceVariable, jToken) in writeInfoLists)
|
||||
{
|
||||
@@ -690,8 +699,18 @@ public abstract class CollectBase : DriverBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var writePList = writeInfoLists.Where(a => !CurrentDevice.OtherVariableRunTimes.Contains(a.Key));
|
||||
var writeSList = writeInfoLists.Where(a => CurrentDevice.OtherVariableRunTimes.Contains(a.Key));
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
foreach (var item in writeSList)
|
||||
{
|
||||
results.TryAdd(item.Key.Name, item.Key.SetValue(item.Value, now));
|
||||
}
|
||||
|
||||
// 过滤掉转换失败的变量,只保留写入成功的变量进行写入操作
|
||||
var results1 = await WriteValuesAsync(writeInfoLists
|
||||
var results1 = await WriteValuesAsync(writePList
|
||||
.Where(a => !results.Any(b => b.Key == a.Key.Name))
|
||||
.ToDictionary(item => item.Key, item => item.Value),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -134,7 +134,7 @@ public abstract class DriverBase : DisposableObject
|
||||
{
|
||||
if (Protocol != null)
|
||||
{
|
||||
FoundataionConfig.ConfigurePlugins(Protocol.ConfigurePlugins());
|
||||
FoundataionConfig?.ConfigurePlugins(Protocol.ConfigurePlugins());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ public abstract class DriverBase : DisposableObject
|
||||
/// <summary>
|
||||
/// 底层驱动配置
|
||||
/// </summary>
|
||||
public TouchSocketConfig FoundataionConfig => ChannelThread?.FoundataionConfig;
|
||||
public TouchSocketConfig? FoundataionConfig => ChannelThread?.FoundataionConfig;
|
||||
|
||||
/// <summary>
|
||||
/// 日志
|
||||
|
||||
@@ -51,6 +51,11 @@ public class InternalTableColumn(string fieldName, Type fieldType, string? field
|
||||
public string? PlaceHolder { get; set; }
|
||||
public Type PropertyType => fieldType;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public ILookupService? LookupService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
@@ -91,7 +96,7 @@ public class InternalTableColumn(string fieldName, Type fieldType, string? field
|
||||
public RenderFragment<ITableColumn>? ToolboxTemplate { get; set; }
|
||||
public IFilter? Filter { get; set; }
|
||||
public string? FormatString { get; set; }
|
||||
public Func<object?, Task<string?>>? Formatter { get; set; }
|
||||
public Func<object, Task<string?>>? Formatter { get; set; }
|
||||
public Alignment? Align { get; set; }
|
||||
public bool? ShowTips { get; set; }
|
||||
public Func<object?, Task<string?>>? GetTooltipTextCallback { get; set; }
|
||||
|
||||
@@ -57,6 +57,11 @@ public interface IPluginService
|
||||
/// </summary>
|
||||
public QueryData<PluginOutput> Page(QueryPageOptions options, PluginTypeEnum? pluginTypeEnum = null);
|
||||
|
||||
/// <summary>
|
||||
/// 重载插件
|
||||
/// </summary>
|
||||
void Reload();
|
||||
|
||||
/// <summary>
|
||||
/// 添加插件
|
||||
/// </summary>
|
||||
|
||||
@@ -38,7 +38,7 @@ internal sealed class PluginService : IPluginService
|
||||
/// <summary>
|
||||
/// 插件驱动文件夹名称
|
||||
/// </summary>
|
||||
public const string DirName = "Plugins";
|
||||
public const string DirName = "GatewayPlugins";
|
||||
|
||||
private const string _cacheKeyGetPluginOutputs = $"{ThingsGatewayCacheConst.Cache_Prefix}{nameof(PluginService)}{nameof(GetList)}";
|
||||
private const string SaveEx = ".save";
|
||||
@@ -63,13 +63,25 @@ internal sealed class PluginService : IPluginService
|
||||
//创建插件文件夹
|
||||
Directory.CreateDirectory(AppContext.BaseDirectory.CombinePathWithOs(PluginService.DirName));
|
||||
//主程序上下文驱动类字典
|
||||
_driverBaseDict = new(App.EffectiveTypes
|
||||
.Where(x => (typeof(CollectBase).IsAssignableFrom(x) || typeof(BusinessBase).IsAssignableFrom(x)) && x.IsClass && !x.IsAbstract)
|
||||
.ToDictionary(a => $"{Path.GetFileNameWithoutExtension(new FileInfo(a.Assembly.Location).Name)}.{a.Name}"));
|
||||
_defaultDriverBaseDict = new(App.EffectiveTypes
|
||||
.Where(x => (typeof(CollectBase).IsAssignableFrom(x) || typeof(BusinessBase).IsAssignableFrom(x)) && x.IsClass && !x.IsAbstract)
|
||||
.ToDictionary(a => $"{Path.GetFileNameWithoutExtension(new FileInfo(a.Assembly.Location).Name)}.{a.Name}"));
|
||||
|
||||
DeleteBackup(DirName);
|
||||
DeleteBackup(AppContext.BaseDirectory);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件文件名称/插件域
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<string, (AssemblyLoadContext AssemblyLoadContext, Assembly Assembly)> _assemblyLoadContextDict { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 主程序上下文中的插件FullName/插件Type
|
||||
/// </summary>
|
||||
private System.Collections.ObjectModel.ReadOnlyDictionary<string, Type> _defaultDriverBaseDict { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件FullName/插件Type
|
||||
/// </summary>
|
||||
@@ -92,8 +104,18 @@ internal sealed class PluginService : IPluginService
|
||||
// 解析插件名称,获取文件名和类型名
|
||||
var filtResult = PluginServiceUtil.GetFileNameAndTypeName(pluginName);
|
||||
|
||||
// 如果是默认键,则搜索主程序上下文中的类型
|
||||
if (_defaultDriverBaseDict.TryGetValue(pluginName, out var type))
|
||||
{
|
||||
var driver = (DriverBase)Activator.CreateInstance(type);
|
||||
if (!type.Assembly.Location.IsNullOrEmpty())
|
||||
driver.Directory = Path.GetDirectoryName(type.Assembly.Location);
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
// 构建插件目录路径
|
||||
var dir = AppContext.BaseDirectory.CombinePathWithOs(DirName);
|
||||
var dir = AppContext.BaseDirectory.CombinePathWithOs(DirName, filtResult.FileName);
|
||||
|
||||
// 先判断是否已经拥有插件模块
|
||||
if (_driverBaseDict.TryGetValue(pluginName, out var value))
|
||||
@@ -102,11 +124,35 @@ internal sealed class PluginService : IPluginService
|
||||
driver.Directory = dir;
|
||||
return driver;
|
||||
}
|
||||
else
|
||||
|
||||
Assembly assembly = null;
|
||||
// 根据路径获取DLL文件
|
||||
var path = dir.CombinePathWithOs($"{filtResult.FileName}.dll");
|
||||
assembly = GetAssembly(path, filtResult.FileName);
|
||||
|
||||
if (assembly != null)
|
||||
{
|
||||
// 根据采集/业务类型获取实际插件类
|
||||
var driverType = assembly.GetTypes()
|
||||
.Where(x => (typeof(CollectBase).IsAssignableFrom(x) || typeof(BusinessBase).IsAssignableFrom(x)) && x.IsClass && !x.IsAbstract)
|
||||
.FirstOrDefault(it => it.Name == filtResult.TypeName);
|
||||
|
||||
if (driverType != null)
|
||||
{
|
||||
var driver = (DriverBase)Activator.CreateInstance(driverType);
|
||||
_logger?.LogInformation(Localizer[$"LoadTypeSuccess", pluginName]);
|
||||
_driverBaseDict.TryAdd(pluginName, driverType);
|
||||
driver.Directory = dir;
|
||||
return driver;
|
||||
}
|
||||
// 抛出异常,插件类型不存在
|
||||
throw new(Localizer[$"LoadTypeFail1", pluginName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 抛出异常,插件文件不存在
|
||||
throw new(Localizer[$"LoadTypeFail2", path]);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -288,6 +334,29 @@ internal sealed class PluginService : IPluginService
|
||||
return query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除全部插件
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.Wait();
|
||||
_driverBaseDict.Clear();
|
||||
foreach (var item in _assemblyLoadContextDict)
|
||||
{
|
||||
item.Value.AssemblyLoadContext.Unload();
|
||||
}
|
||||
GC.Collect();
|
||||
ClearCache();
|
||||
_assemblyLoadContextDict.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_locker.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步保存驱动程序信息。
|
||||
/// </summary>
|
||||
@@ -307,9 +376,24 @@ internal sealed class PluginService : IPluginService
|
||||
var maxFileSize = 100 * 1024 * 1024; // 最大100MB
|
||||
|
||||
// 获取主程序集文件名
|
||||
//var mainFileName = Path.GetFileNameWithoutExtension(plugin.MainFile.Name);
|
||||
// 构建插件文件夹绝对路径
|
||||
var fullDir = AppContext.BaseDirectory.CombinePathWithOs(DirName);
|
||||
var mainFileName = Path.GetFileNameWithoutExtension(plugin.MainFile.Name);
|
||||
string fullDir = string.Empty;
|
||||
bool isDefaultDriver = false;
|
||||
//判定是否上下文程序集
|
||||
var defaultDriver = _defaultDriverBaseDict.FirstOrDefault(a => Path.GetFileNameWithoutExtension(new FileInfo(a.Value.Assembly.Location).Name) == mainFileName);
|
||||
if (defaultDriver.Value != null)
|
||||
{
|
||||
var filtResult = PluginServiceUtil.GetFileNameAndTypeName(defaultDriver.Key);
|
||||
fullDir = Path.GetDirectoryName(filtResult.FileName);
|
||||
isDefaultDriver = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 构建插件文件夹绝对路径
|
||||
fullDir = AppContext.BaseDirectory.CombinePathWithOs(DirName, mainFileName);
|
||||
isDefaultDriver = false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 构建主程序集绝对路径
|
||||
@@ -355,25 +439,56 @@ internal sealed class PluginService : IPluginService
|
||||
{
|
||||
throw new(Localizer[$"PluginNotFound"]);
|
||||
}
|
||||
|
||||
assembly = null;
|
||||
|
||||
|
||||
|
||||
// 将主程序集保存到文件
|
||||
await MarkSave(fullPath, mainMemoryStream).ConfigureAwait(false);
|
||||
// 将其他文件保存到文件
|
||||
foreach (var item in otherFilesStreams)
|
||||
if (isDefaultDriver)
|
||||
{
|
||||
await MarkSave(fullDir.CombinePathWithOs(item.Name), item.MemoryStream).ConfigureAwait(false);
|
||||
// 将主程序集保存到文件
|
||||
await MarkSave(fullPath, mainMemoryStream).ConfigureAwait(false);
|
||||
// 将其他文件保存到文件
|
||||
foreach (var item in otherFilesStreams)
|
||||
{
|
||||
await MarkSave(fullDir.CombinePathWithOs(item.Name), item.MemoryStream).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// 将主程序集保存到文件
|
||||
mainMemoryStream.Seek(0, SeekOrigin.Begin);
|
||||
Directory.CreateDirectory(fullDir);// 创建插件文件夹
|
||||
using FileStream fs = new(fullPath, FileMode.Create);
|
||||
await mainMemoryStream.CopyToAsync(fs).ConfigureAwait(false);
|
||||
// 将其他文件保存到文件
|
||||
foreach (var item in otherFilesStreams)
|
||||
{
|
||||
item.MemoryStream.Seek(0, SeekOrigin.Begin);
|
||||
using FileStream fs1 = new(fullDir.CombinePathWithOs(item.Name), FileMode.Create);
|
||||
await item.MemoryStream.CopyToAsync(fs1).ConfigureAwait(false);
|
||||
await item.MemoryStream.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
// 卸载程序集加载上下文并清除缓存
|
||||
assemblyLoadContext.Unload();
|
||||
|
||||
ClearCache();
|
||||
|
||||
try
|
||||
{
|
||||
// 卸载相同文件的插件域
|
||||
DeletePlugin(mainFileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -458,7 +573,25 @@ internal sealed class PluginService : IPluginService
|
||||
lock (this)
|
||||
{
|
||||
App.CacheService.Remove(_cacheKeyGetPluginOutputs);
|
||||
App.CacheService.DelByPattern($"{nameof(PluginService)}_");
|
||||
|
||||
//多语言缓存清理
|
||||
try
|
||||
{
|
||||
// 获取私有字段
|
||||
FieldInfo fieldInfo = typeof(ResourceManagerStringLocalizerFactory).GetField("_localizerCache", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
// 获取字段的值
|
||||
var dictionary = (ConcurrentDictionary<string, ResourceManagerStringLocalizer>)fieldInfo.GetValue(App.StringLocalizerFactory);
|
||||
foreach (var item in _assemblyLoadContextDict)
|
||||
{
|
||||
// 移除特定键
|
||||
dictionary.RemoveWhere(a => item.Value.Assembly.ExportedTypes.Select(b => b.AssemblyQualifiedName).Contains(a.Key));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
_dispatchService.Dispatch(new());
|
||||
@@ -468,6 +601,104 @@ internal sealed class PluginService : IPluginService
|
||||
|
||||
#endregion public
|
||||
|
||||
/// <summary>
|
||||
/// 删除插件域,卸载插件
|
||||
/// </summary>
|
||||
/// <param name="path">主程序集文件名称</param>
|
||||
private void DeletePlugin(string path)
|
||||
{
|
||||
if (_assemblyLoadContextDict.TryGetValue(path, out var assemblyLoadContext))
|
||||
{
|
||||
//移除字典
|
||||
_driverBaseDict.RemoveWhere(a => path == PluginServiceUtil.GetFileNameAndTypeName(a.Key).FileName);
|
||||
_assemblyLoadContextDict.Remove(path);
|
||||
//卸载
|
||||
assemblyLoadContext.AssemblyLoadContext.Unload();
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取程序集
|
||||
/// </summary>
|
||||
/// <param name="path">插件主文件绝对路径</param>
|
||||
/// <param name="fileName">插件主文件名称</param>
|
||||
/// <returns></returns>
|
||||
private Assembly GetAssembly(string path, string fileName)
|
||||
{
|
||||
Assembly assembly = null;
|
||||
_logger?.LogInformation(Localizer["AddPluginFile", path]);
|
||||
//全部程序集路径
|
||||
List<string> paths = new();
|
||||
Directory.GetFiles(Path.GetDirectoryName(path), "*.dll").ToList().ForEach(a => paths.Add(a));
|
||||
|
||||
if (_assemblyLoadContextDict.TryGetValue(fileName, out (AssemblyLoadContext AssemblyLoadContext, Assembly Assembly) value))
|
||||
{
|
||||
assembly = value.Assembly;
|
||||
}
|
||||
else
|
||||
{
|
||||
//新建插件域,并注明可卸载
|
||||
var assemblyLoadContext = new AssemblyLoadContext(fileName, true);
|
||||
//获取插件程序集
|
||||
assembly = GetAssembly(path, paths, assemblyLoadContext);
|
||||
if (assembly == null)
|
||||
{
|
||||
assemblyLoadContext.Unload();
|
||||
return null;
|
||||
}
|
||||
//添加到全局对象
|
||||
_assemblyLoadContextDict.TryAdd(fileName, (assemblyLoadContext, assembly));
|
||||
}
|
||||
return assembly;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取程序集
|
||||
/// </summary>
|
||||
/// <param name="path">主程序的路径</param>
|
||||
/// <param name="paths">全部文件的路径</param>
|
||||
/// <param name="assemblyLoadContext">当前插件域</param>
|
||||
/// <returns></returns>
|
||||
private Assembly GetAssembly(string path, List<string> paths, AssemblyLoadContext assemblyLoadContext)
|
||||
{
|
||||
Assembly assembly = null;
|
||||
//var cacheId = CommonUtils.GetSingleId();
|
||||
//foreach (var item in paths)
|
||||
//{
|
||||
// var dir = Path.GetDirectoryName(item).CombinePathWithOs($"Cache{cacheId}");
|
||||
// var cachePath = dir.CombinePath(Path.GetFileName(item));
|
||||
// Directory.CreateDirectory(dir);
|
||||
// File.Copy(item, cachePath, true);
|
||||
//}
|
||||
foreach (var item in paths)
|
||||
{
|
||||
using var fs = new FileStream(item, FileMode.Open);
|
||||
//var cachePath = Path.GetDirectoryName(item).CombinePathWithOs($"Cache{cacheId}").CombinePath(Path.GetFileName(item));
|
||||
if (item == path)
|
||||
{
|
||||
assembly = assemblyLoadContext.LoadFromStream(fs); //加载主程序集,并获取
|
||||
|
||||
//修改为从文件创立,满足roslyn引擎的要求
|
||||
//assembly = assemblyLoadContext.LoadFromAssemblyPath(cachePath);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
//assemblyLoadContext.LoadFromAssemblyPath(cachePath);
|
||||
assemblyLoadContext.LoadFromStream(fs); //加载主程序集,并获取
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogWarning(ex, Localizer[$"LoadOtherFileFail", item]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return assembly;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取全部插件信息
|
||||
/// </summary>
|
||||
@@ -510,8 +741,8 @@ internal sealed class PluginService : IPluginService
|
||||
List<PluginOutput> plugins = new List<PluginOutput>();
|
||||
// 主程序上下文
|
||||
|
||||
// 遍历程序集上下文插件驱动字典,生成插件驱动信息
|
||||
foreach (var item in _driverBaseDict)
|
||||
// 遍历程序集上下文默认驱动字典,生成默认驱动插件信息
|
||||
foreach (var item in _defaultDriverBaseDict)
|
||||
{
|
||||
if (PluginServiceUtil.IsSupported(item.Value))
|
||||
{
|
||||
@@ -531,10 +762,59 @@ internal sealed class PluginService : IPluginService
|
||||
};
|
||||
pluginOutput.DeviceCount = App.GetService<IDeviceService>().GetAll().Count(a => a.PluginName == pluginOutput.FullName);//关联设备数量
|
||||
plugins.Add(pluginOutput);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 获取插件文件夹路径列表
|
||||
string[] folderPaths = Directory.GetDirectories(AppContext.BaseDirectory.CombinePathWithOs(DirName));
|
||||
|
||||
// 遍历插件文件夹
|
||||
foreach (string folderPath in folderPaths)
|
||||
{
|
||||
//当前插件文件夹
|
||||
|
||||
try
|
||||
{
|
||||
var driverMainName = Path.GetFileName(folderPath);
|
||||
FileInfo fileInfo = new FileInfo(folderPath.CombinePathWithOs($"{driverMainName}.dll")); //插件主程序集名称约定为文件夹名称.dll
|
||||
DateTime lastWriteTime = fileInfo.LastWriteTime;
|
||||
|
||||
// 加载插件程序集并获取其中的驱动类型信息
|
||||
var assembly = GetAssembly(folderPath.CombinePathWithOs($"{driverMainName}.dll"), driverMainName);
|
||||
var driverTypes = assembly.GetTypes().Where(x => (typeof(CollectBase).IsAssignableFrom(x) || typeof(BusinessBase).IsAssignableFrom(x)) && x.IsClass && !x.IsAbstract);
|
||||
|
||||
// 遍历驱动类型,生成插件信息,并将其添加到插件列表中
|
||||
foreach (var type in driverTypes)
|
||||
{
|
||||
if (PluginServiceUtil.IsSupported(type))
|
||||
{
|
||||
// 先判断是否已经拥有插件模块
|
||||
if (!_driverBaseDict.ContainsKey($"{driverMainName}.{type.Name}"))
|
||||
{
|
||||
//添加到字典
|
||||
_driverBaseDict.TryAdd($"{driverMainName}.{type.Name}", type);
|
||||
_logger?.LogInformation(Localizer[$"LoadTypeSuccess", PluginServiceUtil.GetFullName(driverMainName, type.Name)]);
|
||||
}
|
||||
plugins.Add(
|
||||
new PluginOutput()
|
||||
{
|
||||
Name = type.Name, //类型名称
|
||||
FileName = $"{driverMainName}", //主程序集名称
|
||||
PluginType = (typeof(CollectBase).IsAssignableFrom(type)) ? PluginTypeEnum.Collect : PluginTypeEnum.Business,//插件类型
|
||||
Version = assembly.GetName().Version.ToString(),//插件版本
|
||||
LastWriteTime = lastWriteTime, //编译时间
|
||||
EducationPlugin = PluginServiceUtil.IsEducation(type),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 记录加载插件失败的日志
|
||||
_logger?.LogWarning(ex, Localizer[$"LoadPluginFail", Path.GetRelativePath(AppContext.BaseDirectory.CombinePathWithOs(DirName), folderPath)]);
|
||||
}
|
||||
}
|
||||
return plugins.OrderBy(a => a.EducationPlugin).ThenByDescending(a => a.DeviceCount).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,11 +79,9 @@ public interface IVariableService
|
||||
Task ImportVariableAsync(Dictionary<string, ImportPreviewOutputBase> input);
|
||||
|
||||
/// <summary>
|
||||
/// 创建n个modbus变量,n/1000个设备,n/1000个通道,1个modbus 模拟服务端
|
||||
/// 创建n个modbus变量
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
Task InsertTestDataAsync(int count);
|
||||
Task InsertTestDataAsync(int variableCount, int deviceCount, string slaveUrl = "127.0.0.1:502");
|
||||
|
||||
/// <summary>
|
||||
/// 表格查询
|
||||
|
||||
@@ -67,15 +67,16 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
|
||||
|
||||
#region 测试
|
||||
|
||||
public async Task InsertTestDataAsync(int count)
|
||||
public async Task InsertTestDataAsync(int variableCount, int deviceCount, string slaveUrl = "127.0.0.1:502")
|
||||
{
|
||||
if (slaveUrl.IsNullOrWhiteSpace()) slaveUrl = "127.0.0.1:502";
|
||||
if (deviceCount > variableCount) variableCount = deviceCount;
|
||||
List<Channel> newChannels = new();
|
||||
List<Device> newDevices = new();
|
||||
List<Variable> newVariables = new();
|
||||
var addressNum = 1;
|
||||
var variableCount = 10000;
|
||||
var channelCount = Math.Max(count / variableCount, 1);
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
var groupVariableCount = (int)Math.Ceiling((decimal)variableCount / deviceCount);
|
||||
for (int i = 0; i < deviceCount; i++)
|
||||
{
|
||||
Channel channel = new Channel();
|
||||
Device device = new Device();
|
||||
@@ -87,7 +88,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
|
||||
channel.Id = id;
|
||||
channel.CreateUserId = UserManager.UserId;
|
||||
channel.CreateOrgId = UserManager.OrgId;
|
||||
channel.RemoteUrl = "127.0.0.1:502";
|
||||
channel.RemoteUrl = slaveUrl;
|
||||
//动态插件属性默认
|
||||
newChannels.Add(channel);
|
||||
}
|
||||
@@ -98,21 +99,23 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
|
||||
device.Id = id;
|
||||
device.PluginType = PluginTypeEnum.Collect;
|
||||
device.ChannelId = channel.Id;
|
||||
device.IntervalTime = 1000;
|
||||
device.IntervalTime = "1000";
|
||||
device.CreateUserId = UserManager.UserId;
|
||||
device.CreateOrgId = UserManager.OrgId;
|
||||
device.PluginName = "ThingsGateway.Plugin.Modbus.ModbusMaster";
|
||||
//动态插件属性默认
|
||||
newDevices.Add(device);
|
||||
}
|
||||
if (channelCount == i + 1 && (count % 10000) != 0)
|
||||
variableCount = Math.Min(count % 10000, 10000);
|
||||
for (int i1 = 0; i1 < variableCount; i1++)
|
||||
if (i != 0 && i == deviceCount - 1)
|
||||
{
|
||||
groupVariableCount = variableCount - deviceCount * (groupVariableCount - 1);
|
||||
}
|
||||
for (int i1 = 0; i1 < groupVariableCount; i1++)
|
||||
{
|
||||
addressNum++;
|
||||
if (addressNum >= 65500)
|
||||
addressNum = 1;
|
||||
var address = $"4{addressNum}";
|
||||
addressNum++;
|
||||
var id = CommonUtils.GetSingleId();
|
||||
var name = $"testVariable{id}";
|
||||
Variable variable = new Variable();
|
||||
@@ -135,6 +138,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
|
||||
var name = $"testChannel{id}";
|
||||
serviceChannel.ChannelType = ChannelTypeEnum.TcpService;
|
||||
serviceChannel.Name = name;
|
||||
serviceChannel.Enable = true;
|
||||
serviceChannel.CreateUserId = UserManager.UserId;
|
||||
serviceChannel.CreateOrgId = UserManager.OrgId;
|
||||
serviceChannel.Id = id;
|
||||
@@ -150,11 +154,41 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
|
||||
serviceDevice.CreateUserId = UserManager.UserId;
|
||||
serviceDevice.CreateOrgId = UserManager.OrgId;
|
||||
serviceDevice.ChannelId = serviceChannel.Id;
|
||||
serviceDevice.IntervalTime = 1000;
|
||||
serviceDevice.IntervalTime = "1000";
|
||||
serviceDevice.PluginName = "ThingsGateway.Plugin.Modbus.ModbusSlave";
|
||||
newDevices.Add(serviceDevice);
|
||||
}
|
||||
|
||||
Channel mqttChannel = new Channel();
|
||||
Device mqttDevice = new Device();
|
||||
|
||||
{
|
||||
var id = CommonUtils.GetSingleId();
|
||||
var name = $"testChannel{id}";
|
||||
mqttChannel.ChannelType = ChannelTypeEnum.Other;
|
||||
mqttChannel.Name = name;
|
||||
mqttChannel.CreateUserId = UserManager.UserId;
|
||||
mqttChannel.CreateOrgId = UserManager.OrgId;
|
||||
mqttChannel.Id = id;
|
||||
newChannels.Add(mqttChannel);
|
||||
}
|
||||
{
|
||||
var id = CommonUtils.GetSingleId();
|
||||
var name = $"testDevice{id}";
|
||||
mqttDevice.Name = name;
|
||||
mqttDevice.PluginType = PluginTypeEnum.Business;
|
||||
mqttDevice.Id = id;
|
||||
mqttDevice.CreateUserId = UserManager.UserId;
|
||||
mqttDevice.CreateOrgId = UserManager.OrgId;
|
||||
mqttDevice.ChannelId = mqttChannel.Id;
|
||||
mqttDevice.IntervalTime = "1000";
|
||||
mqttDevice.PluginName = "ThingsGateway.Plugin.Mqtt.MqttServer";
|
||||
mqttDevice.DevicePropertys = new Dictionary<string, string>
|
||||
{
|
||||
{"IsAllVariable", "true"}
|
||||
};
|
||||
newDevices.Add(mqttDevice);
|
||||
}
|
||||
using var db = GetDB();
|
||||
|
||||
var result = await db.UseTranAsync(async () =>
|
||||
|
||||
@@ -19,6 +19,23 @@ public class Startup : AppStartup
|
||||
{
|
||||
public void ConfigureAdminApp(IServiceCollection services)
|
||||
{
|
||||
|
||||
var tempDir = Path.Combine(AppContext.BaseDirectory, "CSSCRIPT");
|
||||
if (Directory.Exists(tempDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempDir);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(tempDir);//重新创建,防止缓存的一些目录信息错误
|
||||
Environment.SetEnvironmentVariable("CSS_CUSTOM_TEMPDIR", tempDir); //传入变量
|
||||
|
||||
//底层多语言配置
|
||||
//Foundation.LocalizerUtil.SetLocalizerFactory((a) => App.CreateLocalizerByType(a));
|
||||
|
||||
|
||||
@@ -1,35 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="$(SolutionDir)PackNuget.props" />
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="$(SolutionDir)PackNuget.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.0" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.1" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="5.0.0" />
|
||||
<PackageReference Include="TouchSocket.Dmtp" Version="3.0.10" />
|
||||
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.0.10" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Admin.Application" Version="$(AdminVersion)" />
|
||||
</ItemGroup>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Locales\*.json" />
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Admin\src\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="SeedData\Gateway\*.json" />
|
||||
<Content Include="SeedData\Gateway\*.json" Pack="true" PackagePath="\Content\SeedData\Gateway\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Remove="Locales\*.json" />
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="SeedData\Gateway\*.json" />
|
||||
<Content Include="SeedData\Gateway\*.json" Pack="true" PackagePath="\Content\SeedData\Gateway\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.CSScript\ThingsGateway.CSScript.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.CSScript\ThingsGateway.CSScript.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
|
||||
"ThingsGateway.Gateway.Razor.PluginPage": {
|
||||
"Reload": "Reload"
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Razor.TcpSessionClientDto": {
|
||||
"Id": "Id",
|
||||
@@ -62,7 +64,7 @@
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.SavePlugin": {
|
||||
"SavePlugin": "Note: Plugins with the same file name will be overwritten",
|
||||
"SavePlugin1": "Plugin changes will take effect after restarting the software"
|
||||
"SavePlugin1": "Plugin changes may take effect after restarting the software"
|
||||
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.BackendLogPage": {
|
||||
@@ -92,7 +94,9 @@
|
||||
"ThingsGateway.Gateway.Razor.VariablePage": {
|
||||
"ImportExcel": "Import Variable",
|
||||
"Clear": "Clear",
|
||||
"TestCount": "TestVariableCount",
|
||||
"TestVariableCount": "TestVariableCount",
|
||||
"TestDeviceCount": "TestDeviceCount",
|
||||
"SlaveUrl": "SlaveUrl",
|
||||
"Test": "AddTestVariable"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.DeviceEditComponent": {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
|
||||
"ThingsGateway.Gateway.Razor.PluginPage": {
|
||||
"Reload": "重载"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.TcpSessionClientDto": {
|
||||
"Id": "Id",
|
||||
"IP": "IP",
|
||||
@@ -61,7 +63,7 @@
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.SavePlugin": {
|
||||
"SavePlugin": "注意:文件名称相同的插件将被覆盖",
|
||||
"SavePlugin1": "插件变动需重启软件后生效"
|
||||
"SavePlugin1": "插件变动可能需重启软件后生效"
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Razor.BackendLogPage": {
|
||||
@@ -91,7 +93,9 @@
|
||||
"ThingsGateway.Gateway.Razor.VariablePage": {
|
||||
"ImportExcel": "导入变量",
|
||||
"Clear": "清空",
|
||||
"TestCount": "测试变量数量",
|
||||
"TestVariableCount": "变量数量",
|
||||
"TestDeviceCount": "采集设备数量",
|
||||
"SlaveUrl": "服务端Url",
|
||||
"Test": "一键添加测试变量"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.DeviceEditComponent": {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
|
||||
"ThingsGateway.Gateway.Razor.PluginPage": {
|
||||
"Reload": "重載"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.TcpSessionClientDto": {
|
||||
"Id": "Id",
|
||||
"IP": "IP",
|
||||
@@ -59,7 +61,7 @@
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.SavePlugin": {
|
||||
"SavePlugin": "注意:文件名稱相同的插件將被覆蓋",
|
||||
"SavePlugin1": "挿件變動需重啓軟件後生效"
|
||||
"SavePlugin1": "挿件變動可能需重啓軟件後生效"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.BackendLogPage": {
|
||||
"BackendLog": "網關後台日誌",
|
||||
@@ -88,7 +90,9 @@
|
||||
"ThingsGateway.Gateway.Razor.VariablePage": {
|
||||
"ImportExcel": "導入變量",
|
||||
"Clear": "清空",
|
||||
"TestCount": "測試變量數量",
|
||||
"TestVariableCount": "變量數量",
|
||||
"TestDeviceCount": "採集設備數量",
|
||||
"SlaveUrl": "服務端Url",
|
||||
"Test": "一鍵添加測試變量"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.DeviceEditComponent": {
|
||||
|
||||
@@ -6,9 +6,16 @@
|
||||
@using ThingsGateway.Gateway.Application
|
||||
@namespace ThingsGateway.Gateway.Razor
|
||||
|
||||
<ValidateForm Model="Model.PluginPropertyModel.Value" @ref=Model.PluginPropertyModel.ValidateForm Id="@Model.Id.ToString()">
|
||||
|
||||
<EditorFormObject class="p-2" Items=PluginPropertyEditorItems AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 ShowLabelTooltip=true LabelWidth=250 Model="Model.PluginPropertyModel.Value" @key=Model.PluginPropertyModel.Value.GetType().TypeHandle.Value>
|
||||
<ValidateForm Model="Model.PluginPropertyModel.Value"
|
||||
@key=@($"DeviceEditValidateForm{Model.Id}{Model.PluginPropertyModel.Value.GetType().TypeHandle.Value}")
|
||||
|
||||
@ref=Model.PluginPropertyModel.ValidateForm
|
||||
Id=@($"DeviceEditValidateForm{Model.Id}{Model.PluginPropertyModel.Value.GetType().TypeHandle.Value}")
|
||||
>
|
||||
|
||||
<EditorFormObject class="p-2" Items=PluginPropertyEditorItems AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 ShowLabelTooltip=true LabelWidth=250 Model="Model.PluginPropertyModel.Value" @key=@($"DeviceEditEditorFormObject{Model.Id}{Model.PluginPropertyModel.Value.GetType().TypeHandle.Value}")
|
||||
>
|
||||
|
||||
<FieldItems>
|
||||
@if (Model.PluginPropertyModel.Value is BusinessPropertyWithCacheIntervalScript businessProperty)
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<TableToolbarButton TItem="PluginOutput" Color="Color.Info" Icon="fa fa-plus" Text="@RazorLocalizer["Add"]"
|
||||
OnClickCallback="OnAdd" IsShow=@(AuthorizeButton("添加")) />
|
||||
|
||||
<TableToolbarButton TItem="PluginOutput" Color="Color.Warning" Icon="fa-solid fa-rotate" Text="@PluginPageLoaclozer["Reload"]"
|
||||
OnClick="OnReload" IsShow=@(AuthorizeButton("添加")) />
|
||||
|
||||
</TableToolbarTemplate>
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name">
|
||||
|
||||
@@ -54,6 +54,9 @@ public partial class PluginPage
|
||||
[Inject]
|
||||
private IStringLocalizer<PluginAddInput> PluginAddInputLoaclozer { get; set; }
|
||||
|
||||
[Inject]
|
||||
private IStringLocalizer<PluginPage> PluginPageLoaclozer { get; set; }
|
||||
|
||||
private async Task OnAdd(IEnumerable<PluginOutput> pluginOutputs)
|
||||
{
|
||||
var op = new DialogOption()
|
||||
@@ -76,5 +79,10 @@ public partial class PluginPage
|
||||
await DialogService.Show(op);
|
||||
}
|
||||
|
||||
private void OnReload()
|
||||
{
|
||||
PluginService.Reload();
|
||||
}
|
||||
|
||||
#endregion 添加
|
||||
}
|
||||
|
||||
@@ -8,242 +8,259 @@
|
||||
@if (ValidateEnable)
|
||||
{
|
||||
|
||||
<ValidateForm Model="Model" OnValidSubmit="ValidSubmit">
|
||||
<Tab>
|
||||
<TabItem Text=@Localizer["VariableInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["BasicInformation"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Name" Readonly=BatchEditEnable />
|
||||
<EditorItem @bind-Field="@context.Description" />
|
||||
<EditorItem @bind-Field="@context.Unit" />
|
||||
<EditorItem @bind-Field="@context.ProtectType" />
|
||||
<EditorItem @bind-Field="@context.Enable" />
|
||||
<EditorItem @bind-Field="@context.RpcWriteEnable" />
|
||||
<EditorItem @bind-Field="@context.SaveValue" />
|
||||
<ValidateForm Model="Model" OnValidSubmit="ValidSubmit">
|
||||
<Tab>
|
||||
<TabItem Text=@Localizer["VariableInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["BasicInformation"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Name" Readonly=BatchEditEnable />
|
||||
<EditorItem @bind-Field="@context.Description" />
|
||||
<EditorItem @bind-Field="@context.Unit" />
|
||||
<EditorItem @bind-Field="@context.ProtectType" />
|
||||
<EditorItem @bind-Field="@context.Enable" />
|
||||
<EditorItem @bind-Field="@context.RpcWriteEnable" />
|
||||
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Connection"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Value" />
|
||||
<EditorItem @bind-Field="@context.SaveValue" />
|
||||
|
||||
<EditorItem @bind-Field="@context.DeviceId">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.DeviceId" Items="@CollectDevices" ShowSearch="true" OnSelectedItemChanged="OnDeviceSelectedItemChanged" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Connection"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DataType" />
|
||||
<EditorItem @bind-Field="@context.DeviceId">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.DeviceId" Items="@CollectDevices" ShowSearch="true" OnSelectedItemChanged="OnDeviceSelectedItemChanged" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.IntervalTime" />
|
||||
<EditorItem @bind-Field="@context.DataType" />
|
||||
|
||||
<EditorItem @bind-Field="@context.OtherMethod">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.OtherMethod" Items="@OtherMethods" ShowSearch="true" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.IntervalTime" />
|
||||
|
||||
<EditorItem @bind-Field="@context.RegisterAddress" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.OtherMethod">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.OtherMethod" Items="@OtherMethods" ShowSearch="true" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.ReadExpressions" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.WriteExpressions" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.RegisterAddress" Rows="1" />
|
||||
|
||||
<EditorItem @bind-Field="@context.ReadExpressions" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.WriteExpressions" Rows="1" />
|
||||
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Remark"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Remark1" />
|
||||
<EditorItem @bind-Field="@context.Remark2" />
|
||||
<EditorItem @bind-Field="@context.Remark3" />
|
||||
<EditorItem @bind-Field="@context.Remark4" />
|
||||
<EditorItem @bind-Field="@context.Remark5" />
|
||||
</FieldItems>
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Remark"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Remark1" />
|
||||
<EditorItem @bind-Field="@context.Remark2" />
|
||||
<EditorItem @bind-Field="@context.Remark3" />
|
||||
<EditorItem @bind-Field="@context.Remark4" />
|
||||
<EditorItem @bind-Field="@context.Remark5" />
|
||||
</FieldItems>
|
||||
|
||||
</EditorForm>
|
||||
</EditorForm>
|
||||
|
||||
</TabItem>
|
||||
<TabItem Text=@Localizer["AlarmInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
</TabItem>
|
||||
<TabItem Text=@Localizer["AlarmInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HHRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.HAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LLRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmText" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.CustomRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.AlarmDelay" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</TabItem>
|
||||
</Tab>
|
||||
<div class="form-footer">
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HHRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.HAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LLRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmText" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.CustomRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.AlarmDelay" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</TabItem>
|
||||
</Tab>
|
||||
<div class="form-footer">
|
||||
|
||||
<Button class="mt-2" ButtonType="ButtonType.Submit" Icon="fa-solid fa-floppy-disk" IsAsync Text=@RazorLocalizer["Save"] />
|
||||
</div>
|
||||
</ValidateForm>
|
||||
<Button class="mt-2" ButtonType="ButtonType.Submit" Icon="fa-solid fa-floppy-disk" IsAsync Text=@RazorLocalizer["Save"] />
|
||||
</div>
|
||||
</ValidateForm>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<Tab>
|
||||
<TabItem Text=@Localizer["VariableInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["BasicInformation"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Name" />
|
||||
<EditorItem @bind-Field="@context.Description" />
|
||||
<EditorItem @bind-Field="@context.Unit" />
|
||||
<EditorItem @bind-Field="@context.ProtectType" />
|
||||
<EditorItem @bind-Field="@context.Enable" />
|
||||
<EditorItem @bind-Field="@context.RpcWriteEnable" />
|
||||
<EditorItem @bind-Field="@context.SaveValue" />
|
||||
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Connection"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DeviceId">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.DeviceId" Items="@CollectDevices" ShowSearch="true" OnSelectedItemChanged="OnDeviceSelectedItemChanged" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DataType" />
|
||||
|
||||
<EditorItem @bind-Field="@context.IntervalTime" />
|
||||
|
||||
<EditorItem @bind-Field="@context.OtherMethod">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.OtherMethod" Items="@OtherMethods" ShowSearch="true" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.RegisterAddress" Rows="1" />
|
||||
|
||||
<EditorItem @bind-Field="@context.ReadExpressions" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.WriteExpressions" Rows="1" />
|
||||
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Remark"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Remark1" />
|
||||
<EditorItem @bind-Field="@context.Remark2" />
|
||||
<EditorItem @bind-Field="@context.Remark3" />
|
||||
<EditorItem @bind-Field="@context.Remark4" />
|
||||
<EditorItem @bind-Field="@context.Remark5" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</TabItem>
|
||||
<TabItem Text=@Localizer["AlarmInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HHRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.HAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LLRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmText" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.CustomRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.AlarmDelay" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Text=@Localizer["PluginInformation"]>
|
||||
<div style="min-height:500px" class="px-4">
|
||||
<div class="row g-2 mx-1 form-inline">
|
||||
|
||||
<div class="col-12 col-md-8">
|
||||
<label required="true" style="width:20%">@Localizer["ChoiceBusinessDeviceId"]</label>
|
||||
<Select SkipValidate IsVirtualize @bind-Value="@ChoiceBusinessDeviceId" Items="@BusinessDevices" ShowSearch="true" ShowLabel="false" />
|
||||
<Tab>
|
||||
<TabItem Text=@Localizer["VariableInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["BasicInformation"]</h6>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<Button OnClick="() => RefreshBusinessPropertyClickAsync(ChoiceBusinessDeviceId)">@Localizer["RefreshBusinessProperty"]</Button>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Name" />
|
||||
<EditorItem @bind-Field="@context.Description" />
|
||||
<EditorItem @bind-Field="@context.Unit" />
|
||||
<EditorItem @bind-Field="@context.ProtectType" />
|
||||
<EditorItem @bind-Field="@context.Enable" />
|
||||
<EditorItem @bind-Field="@context.RpcWriteEnable" />
|
||||
|
||||
<EditorItem @bind-Field="@context.Value" />
|
||||
<EditorItem @bind-Field="@context.SaveValue" />
|
||||
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Connection"]</h6>
|
||||
</div>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DeviceId">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.DeviceId" Items="@CollectDevices" ShowSearch="true" OnSelectedItemChanged="OnDeviceSelectedItemChanged" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.DataType" />
|
||||
|
||||
<EditorItem @bind-Field="@context.IntervalTime" />
|
||||
|
||||
<EditorItem @bind-Field="@context.OtherMethod">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12 col-md-6">
|
||||
<Select IsVirtualize @bind-Value="@value.OtherMethod" Items="@OtherMethods" ShowSearch="true" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
|
||||
<EditorItem @bind-Field="@context.RegisterAddress" Rows="1" />
|
||||
|
||||
<EditorItem @bind-Field="@context.ReadExpressions" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.WriteExpressions" Rows="1" />
|
||||
|
||||
|
||||
|
||||
<EditorItem @bind-Field="@context.Description">
|
||||
<EditTemplate Context="value">
|
||||
<div class="col-12">
|
||||
<h6>@Localizer["Remark"]</h6>
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Remark1" />
|
||||
<EditorItem @bind-Field="@context.Remark2" />
|
||||
<EditorItem @bind-Field="@context.Remark3" />
|
||||
<EditorItem @bind-Field="@context.Remark4" />
|
||||
<EditorItem @bind-Field="@context.Remark5" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</TabItem>
|
||||
<TabItem Text=@Localizer["AlarmInformation"]>
|
||||
<EditorForm class="p-2" AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 LabelWidth=250 Model="Model">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolCloseAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmText" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.BoolOpenAlarmEnable" Rows="1" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HHRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HHAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.HAlarmText" />
|
||||
<EditorItem @bind-Field="@context.HAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.HRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.HAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmText" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.LLRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.LLAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmText" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmCode" />
|
||||
<EditorItem @bind-Field="@context.CustomRestrainExpressions" />
|
||||
<EditorItem @bind-Field="@context.CustomAlarmEnable" />
|
||||
<EditorItem @bind-Field="@context.AlarmDelay" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Text=@Localizer["PluginInformation"]>
|
||||
<div style="min-height:500px" class="px-4">
|
||||
<div class="row g-2 mx-1 form-inline">
|
||||
|
||||
<div class="col-12 col-md-8">
|
||||
@* <label required="true" style="width:20%">@Localizer["ChoiceBusinessDeviceId"]</label> *@
|
||||
<Select SkipValidate IsVirtualize @bind-Value="@ChoiceBusinessDeviceId" Items="@BusinessDevices" ShowSearch="true" ShowLabel="true" />
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<Button OnClick="async() =>{
|
||||
|
||||
await RefreshBusinessPropertyClickAsync(ChoiceBusinessDeviceId);
|
||||
foreach (var item in Model.VariablePropertyModels)
|
||||
{
|
||||
if(item.Value!=null)
|
||||
{
|
||||
item.Value.ValidateForm=null;
|
||||
}
|
||||
}
|
||||
}">@Localizer["RefreshBusinessProperty"]</Button>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.VariablePropertyModels != null)
|
||||
{
|
||||
@foreach (var item in Model.VariablePropertyModels)
|
||||
@foreach (var a in Model.VariablePropertyModels)
|
||||
{
|
||||
|
||||
var item = a;
|
||||
|
||||
var custom = VariablePropertyRenderFragments.TryGetValue(item.Key, out var renderFragment);
|
||||
|
||||
if (!custom)
|
||||
@@ -252,31 +269,35 @@ else
|
||||
if (has)
|
||||
{
|
||||
|
||||
<Card IsShadow=true class="m-2 flex-fill" Color="Color.Primary">
|
||||
<HeaderTemplate>
|
||||
|
||||
<Card IsShadow=true class="m-2 flex-fill" Color="Color.Primary">
|
||||
<HeaderTemplate>
|
||||
@{
|
||||
BusinessDeviceDict.TryGetValue(item.Key, out var items);
|
||||
}
|
||||
<div class="flex-fill">
|
||||
<div class="flex-fill">
|
||||
@($"{items.Name} - {PluginServiceUtil.GetFileNameAndTypeName(items?.PluginName).TypeName}")
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button OnClick=@((a)=>
|
||||
{
|
||||
Model.VariablePropertyModels.Remove(item.Key);
|
||||
}) class="mx-2" Color="Color.None" style="color: var(--bs-card-titlecolor);" Icon=@("fas fa-delete-left") />
|
||||
<Button OnClick=@((a)=>
|
||||
{
|
||||
Model.VariablePropertyModels.Remove(item.Key);
|
||||
}) class="mx-2" Color="Color.None" style="color: var(--bs-card-titlecolor);" Icon=@("fas fa-delete-left") />
|
||||
|
||||
</HeaderTemplate>
|
||||
</HeaderTemplate>
|
||||
|
||||
<BodyTemplate>
|
||||
<ValidateForm Model="item.Value.Value" Id=@((item.Key+Model.Id).ToString()) @ref=item.Value.ValidateForm>
|
||||
<BodyTemplate>
|
||||
|
||||
<EditorFormObject class="p-2" Items=items AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 ShowLabelTooltip=true LabelWidth=250 Model="item.Value.Value" @key=item.Value.Value.GetType().TypeHandle.Value>
|
||||
<ValidateForm Model="item.Value.Value" @ref=item.Value.ValidateForm
|
||||
@key=@($"VariableEditValidateForm{item.Key}{Model.Id}{item.Value.Value.GetType().TypeHandle.Value}")
|
||||
Id=@($"VariableEditValidateForm{item.Key}{Model.Id}{item.Value.Value.GetType().TypeHandle.Value}")>
|
||||
|
||||
</EditorFormObject>
|
||||
</ValidateForm>
|
||||
</BodyTemplate>
|
||||
</Card>
|
||||
<EditorFormObject class="p-2" Items=items AutoGenerateAllItem="false" RowType=RowType.Inline ItemsPerRow=2 ShowLabelTooltip=true LabelWidth=250 Model="item.Value.Value" @key=@($"VariableEditEditorFormObject{item.Key}{Model.Id}{item.Value.Value.GetType().TypeHandle.Value}")>
|
||||
|
||||
</EditorFormObject>
|
||||
</ValidateForm>
|
||||
</BodyTemplate>
|
||||
</Card>
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -285,10 +306,10 @@ else
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</TabItem>
|
||||
</Tab>
|
||||
</TabItem>
|
||||
</Tab>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -78,7 +78,9 @@
|
||||
IsAsync OnConfirm=@(InsertTestDataAsync)>
|
||||
|
||||
<BodyTemplate>
|
||||
<BootstrapInput @bind-Value=TestCount ShowLabel="true" ShowLabelTooltip="true" />
|
||||
<BootstrapInput @bind-Value=TestVariableCount ShowLabel="true" ShowLabelTooltip="true" />
|
||||
<BootstrapInput @bind-Value=TestDeviceCount ShowLabel="true" ShowLabelTooltip="true" />
|
||||
<BootstrapInput @bind-Value=SlaveUrl ShowLabel="true" ShowLabelTooltip="true" />
|
||||
</BodyTemplate>
|
||||
|
||||
</PopConfirmButton>
|
||||
|
||||
@@ -38,7 +38,10 @@ public partial class VariablePage : IDisposable
|
||||
[NotNull]
|
||||
private IDispatchService<bool>? DispatchService { get; set; }
|
||||
|
||||
private int TestCount { get; set; }
|
||||
private int TestVariableCount { get; set; }
|
||||
private int TestDeviceCount { get; set; }
|
||||
|
||||
private string SlaveUrl { get; set; }
|
||||
|
||||
|
||||
|
||||
@@ -315,7 +318,7 @@ public partial class VariablePage : IDisposable
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
await VariableService.InsertTestDataAsync(TestCount);
|
||||
await VariableService.InsertTestDataAsync(TestVariableCount, TestDeviceCount, SlaveUrl);
|
||||
await InvokeAsync(async () =>
|
||||
{
|
||||
await ToastService.Default();
|
||||
|
||||
@@ -43,7 +43,9 @@
|
||||
|
||||
@if (_driverBaseItem != null && _driverBaseItem?.CurrentDevice != null && _driverBaseItem.CurrentDevice.Channel.LogEnable == true)
|
||||
{
|
||||
<LogConsole Logger=@_driverBaseItem.LogMessage LogPath=@_driverBaseItem.LogPath HeaderText="@Localizer["LogConsole"]" HeightString="var(--logconsle-height)"></LogConsole>
|
||||
<LogConsole LogLevel=@(_driverBaseItem.LogMessage.LogLevel) LogLevelChanged="(a)=>{
|
||||
_driverBaseItem.LogMessage.LogLevel=a;
|
||||
}" LogPath=@_driverBaseItem.LogPath HeaderText="@Localizer["LogConsole"]" HeightString="var(--logconsle-height)"></LogConsole>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.5" />
|
||||
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.0" />
|
||||
<PackageReference Include="ThingsGateway.Admin.Razor" Version="$(AdminVersion)" />
|
||||
<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.7" />
|
||||
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.1" />
|
||||
<ProjectReference Include="..\..\..\Admin\src\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# 17
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34622.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{0B748352-5D27-4F14-8A20-364034C72867}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
Directory.Build.props = Directory.Build.props
|
||||
FoundationVersion.props = FoundationVersion.props
|
||||
Version.props = Version.props
|
||||
@@ -17,8 +18,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.CSScript", "F
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "Foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{9D49F8E2-A82C-4E36-8F54-4F45BF3E47C0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Razor", "Foundation\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj", "{70665B3C-5E43-4A2B-B032-30986A16DE67}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.SourceGenerator", "Foundation\ThingsGateway.Foundation.SourceGenerator\ThingsGateway.Foundation.SourceGenerator.csproj", "{E325A64C-2B72-4DD0-8A6C-229B29FB95EB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation.Variable", "Foundation\ThingsGateway.Foundation.Variable\ThingsGateway.Foundation.Variable.csproj", "{8EE037EC-ED21-42A0-BE1F-219E9886E43A}"
|
||||
@@ -27,6 +26,31 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Appli
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Razor", "Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj", "{6B92AF2D-0997-4887-B1C5-31861F298238}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Foundation.Razor", "Foundation\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj", "{569F229F-FB10-4789-B00B-D9D12383177A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Admin", "Admin", "{72C65578-92A5-4E99-9779-27835B12B32F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Admin.Application", "..\Admin\src\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{C4C01993-DB12-49D9-BDDB-C312042A6C29}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Admin.Razor", "..\Admin\src\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj", "{BC3AE9E7-7B56-4894-9514-52A493A0D724}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Core", "..\Admin\src\ThingsGateway.Core\ThingsGateway.Core.csproj", "{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Furion", "..\Admin\src\ThingsGateway.Furion\ThingsGateway.Furion.csproj", "{3759E861-BA1E-498A-85CF-48A0BE6B00BB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.NewLife.X", "..\Admin\src\ThingsGateway.NewLife.X\ThingsGateway.NewLife.X.csproj", "{42928B73-237A-4483-935E-E7FAAC52F288}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Razor", "..\Admin\src\ThingsGateway.Razor\ThingsGateway.Razor.csproj", "{015DD6B7-325F-45B5-B69E-CBD62DC6235A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.AdminServer", "..\Admin\src\ThingsGateway.AdminServer\ThingsGateway.AdminServer.csproj", "{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{568A28E1-6CAE-461C-8578-C28BEAC81945}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
..\Admin\src\Admin.props = ..\Admin\src\Admin.props
|
||||
..\Admin\src\PackNuget.props = ..\Admin\src\PackNuget.props
|
||||
..\Admin\src\Version.props = ..\Admin\src\Version.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -41,10 +65,6 @@ Global
|
||||
{9D49F8E2-A82C-4E36-8F54-4F45BF3E47C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9D49F8E2-A82C-4E36-8F54-4F45BF3E47C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9D49F8E2-A82C-4E36-8F54-4F45BF3E47C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{70665B3C-5E43-4A2B-B032-30986A16DE67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70665B3C-5E43-4A2B-B032-30986A16DE67}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70665B3C-5E43-4A2B-B032-30986A16DE67}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70665B3C-5E43-4A2B-B032-30986A16DE67}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E325A64C-2B72-4DD0-8A6C-229B29FB95EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E325A64C-2B72-4DD0-8A6C-229B29FB95EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E325A64C-2B72-4DD0-8A6C-229B29FB95EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -61,6 +81,38 @@ Global
|
||||
{6B92AF2D-0997-4887-B1C5-31861F298238}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B92AF2D-0997-4887-B1C5-31861F298238}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B92AF2D-0997-4887-B1C5-31861F298238}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -68,11 +120,19 @@ Global
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{506232CE-0FB6-4ACB-96DE-C8C8D075A642} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{9D49F8E2-A82C-4E36-8F54-4F45BF3E47C0} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{70665B3C-5E43-4A2B-B032-30986A16DE67} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{E325A64C-2B72-4DD0-8A6C-229B29FB95EB} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{8EE037EC-ED21-42A0-BE1F-219E9886E43A} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{A1163B55-31D8-4F58-872F-1DD5E0F14490} = {5948EA23-4B42-4C22-A266-2E0AE5FA575F}
|
||||
{6B92AF2D-0997-4887-B1C5-31861F298238} = {5948EA23-4B42-4C22-A266-2E0AE5FA575F}
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{568A28E1-6CAE-461C-8578-C28BEAC81945} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {199B1B96-4F56-4828-9531-813BA02DB282}
|
||||
|
||||
@@ -1,126 +1,125 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Admin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Plugin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\CustomPlugin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Custom.targets" />
|
||||
<PropertyGroup>
|
||||
<CustomTargetFramework>$(TargetFramework)</CustomTargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<!--<PublishAot>true</PublishAot>-->
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<!--<Import Project="..\ThingsGateway.Server\targets\Admin.targets" />-->
|
||||
<Import Project="..\ThingsGateway.Server\targets\PluginContext.targets" />
|
||||
<!--<Import Project="..\ThingsGateway.Server\targets\Plugin.targets" />-->
|
||||
<Import Project="..\ThingsGateway.Server\targets\CustomPlugin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Custom.targets" />
|
||||
<PropertyGroup>
|
||||
<CustomTargetFramework>$(TargetFramework)</CustomTargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<!--<PublishAot>true</PublishAot>-->
|
||||
|
||||
<!--动态适用GC-->
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
<!--使用工作站GC-->
|
||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
<!--动态适用GC-->
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
<!--使用工作站GC-->
|
||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net6.0' ">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net8.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="6.0.33" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="6.0.33" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Photino.NET" Version="3.2.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Photino.NET" Version="3.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndex.razor" Link="Index\GatewayIndex.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndex.razor.cs" Link="Index\GatewayIndex.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor" Link="Layout\MainLayout.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\MainLayout.razor.cs" Link="Layout\MainLayout.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor.css" Link="Layout\MainLayout.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\AccessDenied.razor" Link="Layout\AccessDenied.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\AccessDenied.razor.cs" Link="Layout\AccessDenied.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor" Link="Layout\Login.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\Login.razor.cs" Link="Layout\Login.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor.css" Link="Layout\Login.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\NotFound404.razor" Link="Layout\NotFound404.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\NotFound404.razor.cs" Link="Layout\NotFound404.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor" Link="Index\GatewayIndexComponent.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor.cs" Link="Index\GatewayIndexComponent.razor.cs" />
|
||||
|
||||
<Compile Include="..\ThingsGateway.Server\Program\SingleFilePublish.cs" Link="Program\SingleFilePublish.cs" />
|
||||
<ItemGroup>
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndex.razor" Link="Index\GatewayIndex.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndex.razor.cs" Link="Index\GatewayIndex.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor" Link="Layout\MainLayout.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\MainLayout.razor.cs" Link="Layout\MainLayout.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor.css" Link="Layout\MainLayout.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\AccessDenied.razor" Link="Layout\AccessDenied.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\AccessDenied.razor.cs" Link="Layout\AccessDenied.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor" Link="Layout\Login.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\Login.razor.cs" Link="Layout\Login.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor.css" Link="Layout\Login.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\NotFound404.razor" Link="Layout\NotFound404.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\NotFound404.razor.cs" Link="Layout\NotFound404.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor" Link="Index\GatewayIndexComponent.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor.cs" Link="Index\GatewayIndexComponent.razor.cs" />
|
||||
|
||||
<Compile Include="..\ThingsGateway.Server\Program\SingleFilePublish.cs" Link="Program\SingleFilePublish.cs" />
|
||||
|
||||
|
||||
|
||||
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.ico" Link="wwwroot\favicon.ico" />
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.png" Link="wwwroot\favicon.png" />
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.Development.json" Link="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.json" Link="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.ico" Link="wwwroot\favicon.ico" />
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.png" Link="wwwroot\favicon.png" />
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.Development.json" Link="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.json" Link="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<Content Include="..\ThingsGateway.Server\Configuration\*" LinkBase="Configuration">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\ThingsGateway.Server\Configuration\*" LinkBase="Configuration">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\en-US.json" Link="Locales\en-US.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-CN.json" Link="Locales\zh-CN.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-TW.json">
|
||||
<Link>Locales\zh-TW.json</Link>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\en-US.json" Link="Locales\en-US.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-CN.json" Link="Locales\zh-CN.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-TW.json">
|
||||
<Link>Locales\zh-TW.json</Link>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -52,6 +52,7 @@ public class SingleFilePublish : ISingleFilePublish
|
||||
|
||||
"ThingsGateway.CSScript",
|
||||
"ThingsGateway.Foundation" ,
|
||||
"ThingsGateway.Foundation.Razor",
|
||||
"ThingsGateway.Gateway.Application",
|
||||
"ThingsGateway.Gateway.Razor" ,
|
||||
"SqlSugar.TDengineCore",
|
||||
|
||||
@@ -1,112 +1,115 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="targets\Admin.targets" />
|
||||
<Import Project="targets\Plugin.targets" />
|
||||
<Import Project="targets\CustomPlugin.targets" />
|
||||
<Import Project="targets\Custom.targets" />
|
||||
<!--<Import Project="targets\OtherPlugin.targets" />-->
|
||||
<!--<Import Project="targets\OtherPlugin1.targets" />-->
|
||||
<PropertyGroup>
|
||||
<CustomTargetFramework>$(TargetFramework)</CustomTargetFramework>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||
<ApplicationIcon>wwwroot\favicon.ico</ApplicationIcon>
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="targets\PluginContext.targets" />
|
||||
<Import Project="targets\Publish1.targets" />
|
||||
<!--<Import Project="targets\Plugin.targets" />-->
|
||||
<Import Project="targets\CustomPlugin.targets" />
|
||||
<Import Project="targets\Custom.targets" />
|
||||
<!--<Import Project="targets\Admin.targets" />-->
|
||||
<!--<Import Project="targets\OtherPlugin.targets" />-->
|
||||
<!--<Import Project="targets\OtherPlugin1.targets" />-->
|
||||
<PropertyGroup>
|
||||
<CustomTargetFramework>$(TargetFramework)</CustomTargetFramework>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||
<ApplicationIcon>wwwroot\favicon.ico</ApplicationIcon>
|
||||
|
||||
<!--动态适用GC-->
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
<!--使用自托管线程池-->
|
||||
<!--<UseWindowsThreadPool>false</UseWindowsThreadPool> -->
|
||||
<!--动态适用GC-->
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
<!--使用自托管线程池-->
|
||||
<!--<UseWindowsThreadPool>false</UseWindowsThreadPool> -->
|
||||
|
||||
<!--使用工作站GC-->
|
||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
|
||||
<!--使用工作站GC-->
|
||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
|
||||
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="DockerPush.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="DockerPush_arm64.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="DockerPush.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="DockerPush_arm64.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net8.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net6.0' ">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Update="WindowsService">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Dockerfile">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Dockerfile_arm64">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<None Update="pm2-windows.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="pm2-linux.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="thingsgateway.service">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="WindowsServiceCreate.bat">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="WindowsServiceDelete.bat">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Update="WindowsService">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Dockerfile">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Dockerfile_arm64">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
<None Update="pm2-windows.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="pm2-linux.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="thingsgateway.service">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="WindowsServiceCreate.bat">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="WindowsServiceDelete.bat">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(SolutionName)' != 'ThingsGatewayRelease' ">
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="targets\Gateway.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayRelease' " />
|
||||
<Import Project="targets\Admin.targets" Condition=" '$(SolutionName)' == 'ThingsGatewayRelease' " />
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
<Project>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Management" Version="$(ProPluginVersion)" GeneratePathProperty="true"/>
|
||||
<PackageReference Include="ThingsGateway.RulesEngine" Version="$(ProPluginVersion)" GeneratePathProperty="true"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Management" Version="$(ProPluginVersion)" GeneratePathProperty="true"/>
|
||||
<PackageReference Include="ThingsGateway.RulesEngine" Version="$(ProPluginVersion)" GeneratePathProperty="true"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="_ResolveCopyManagementLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
|
||||
<ItemGroup>
|
||||
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'=='ThingsGateway.Management' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="_ResolveCopyRulesEngineLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
|
||||
<ItemGroup>
|
||||
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'=='ThingsGateway.RulesEngine' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="_ResolveCopyManagementLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
|
||||
<ItemGroup>
|
||||
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'=='ThingsGateway.Management' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="_ResolveCopyRulesEngineLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
|
||||
<ItemGroup>
|
||||
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'=='ThingsGateway.RulesEngine' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="CopyManagementNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<ManagementApplicationPackageFiles Include="$(PkgThingsGateway_Management)\Content\SeedData\Management\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ManagementApplicationFolder>$(TargetDir)SeedData\Management\</ManagementApplicationFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(ManagementApplicationFolder)" />
|
||||
<Copy SourceFiles="@(ManagementApplicationPackageFiles)" DestinationFolder="$(ManagementApplicationFolder)%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
<Target Name="CopyRulesEngineNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<RulesEngineApplicationPackageFiles Include="$(PkgThingsGateway_RulesEngine)\Content\SeedData\RulesEngine\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RulesEngineApplicationFolder>$(TargetDir)SeedData\RulesEngine\</RulesEngineApplicationFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(RulesEngineApplicationFolder)" />
|
||||
<Copy SourceFiles="@(RulesEngineApplicationPackageFiles)" DestinationFolder="$(RulesEngineApplicationFolder)%(RecursiveDir)" />
|
||||
<Target Name="CopyManagementNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<ManagementApplicationPackageFiles Include="$(PkgThingsGateway_Management)\Content\SeedData\Management\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ManagementApplicationFolder>$(TargetDir)SeedData\Management\</ManagementApplicationFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(ManagementApplicationFolder)" />
|
||||
<Copy SourceFiles="@(ManagementApplicationPackageFiles)" DestinationFolder="$(ManagementApplicationFolder)%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
</Target>
|
||||
<Target Name="CopyRulesEngineNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<RulesEngineApplicationPackageFiles Include="$(PkgThingsGateway_RulesEngine)\Content\SeedData\RulesEngine\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RulesEngineApplicationFolder>$(TargetDir)SeedData\RulesEngine\</RulesEngineApplicationFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(RulesEngineApplicationFolder)" />
|
||||
<Copy SourceFiles="@(RulesEngineApplicationPackageFiles)" DestinationFolder="$(RulesEngineApplicationFolder)%(RecursiveDir)" />
|
||||
|
||||
|
||||
<Target Name="ManagementPostPublish" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<ManagementFiles Include="bin\$(Configuration)\$(TargetFramework)\SeedData\**" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
<Copy SourceFiles="@(ManagementFiles)" DestinationFolder="$(PublishDir)SeedData\%(RecursiveDir)" />
|
||||
</Target>
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="RulesEnginePostPublish" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<RulesEngineFiles Include="bin\$(Configuration)\$(TargetFramework)\SeedData\**" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
<Copy SourceFiles="@(RulesEngineFiles)" DestinationFolder="$(PublishDir)SeedData\%(RecursiveDir)" />
|
||||
<Target Name="ManagementPostPublish" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<ManagementFiles Include="bin\$(Configuration)\$(TargetFramework)\SeedData\**" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
<Copy SourceFiles="@(ManagementFiles)" DestinationFolder="$(PublishDir)SeedData\%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="RulesEnginePostPublish" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<RulesEngineFiles Include="bin\$(Configuration)\$(TargetFramework)\SeedData\**" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
<Copy SourceFiles="@(RulesEngineFiles)" DestinationFolder="$(PublishDir)SeedData\%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -58,27 +58,27 @@
|
||||
<MainFile3 Include="$(PkgThingsGateway_Plugin_URF_R330)\Main\**" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
|
||||
<PluginFolder>$(TargetDir)GatewayPlugins\</PluginFolder>
|
||||
</PropertyGroup>
|
||||
<Message Text="将插件复制到插件目录 $(PluginFolder)" Importance="high" />
|
||||
|
||||
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HJ212PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_BACnetPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_AllenBradleyCipPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DCONPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_EDPF_NTPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_KELID2008PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_LKSISPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MelsecPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OmronPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DKQ_A16DPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_IDR210PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_URF_R330PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_USBScanerPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_SECSPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_TS550PackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_VigorPackageFiles)" DestinationFolder="$(PluginFolder)%(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="@(MainFile1)" DestinationFolder="$(TargetDir)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(MainFile2)" DestinationFolder="$(TargetDir)%(RecursiveDir)" />
|
||||
|
||||
43
src/ThingsGateway.Server/targets/Gateway.targets
Normal file
43
src/ThingsGateway.Server/targets/Gateway.targets
Normal file
@@ -0,0 +1,43 @@
|
||||
<Project>
|
||||
|
||||
<!--Gateway-->
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Gateway.Razor" Version="$(GatewayVersion)" />
|
||||
<PackageReference Include="ThingsGateway.Gateway.Application" Version="$(GatewayVersion)" 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 -->
|
||||
<GatewayApplicationPackageFiles Include="$(PkgThingsGateway_Gateway_Application)\Content\SeedData\Gateway\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<GatewayApplicationFolder>$(TargetDir)SeedData\Gateway\</GatewayApplicationFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(GatewayApplicationFolder)" />
|
||||
<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>
|
||||
@@ -1,30 +1,33 @@
|
||||
<Project>
|
||||
|
||||
<ItemGroup>
|
||||
<!--MqttYINGKE 插件-->
|
||||
<PackageReference Include="ThingsGateway.Plugin.MqttYINGKE" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
|
||||
<!--HUANANSFSK 插件-->
|
||||
<PackageReference Include="ThingsGateway.Plugin.HUANANSFSK" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
|
||||
<ItemGroup>
|
||||
<!--MqttYINGKE 插件-->
|
||||
<PackageReference Include="ThingsGateway.Plugin.MqttYINGKE" Version="$(ProPluginVersion)" GeneratePathProperty="true" Private="false" IncludeAssets="native;" />
|
||||
<!--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>
|
||||
|
||||
</ItemGroup>
|
||||
<Target Name="CopyOtherPluginNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<PkgThingsGateway_Plugin_MqttYINGKEPackageFiles Include="$(PkgThingsGateway_Plugin_MqttYINGKE)\Content\net6.0\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_HUANANSFSKPackageFiles Include="$(PkgThingsGateway_Plugin_HUANANSFSK)\Content\net6.0\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_YPSFSKPackageFiles Include="$(PkgThingsGateway_Plugin_YPSFSK)\Content\net6.0\**\*.*" />
|
||||
|
||||
<Target Name="CopyOtherPluginNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<PkgThingsGateway_Plugin_MqttYINGKEPackageFiles Include="$(PkgThingsGateway_Plugin_MqttYINGKE)\Content\net6.0\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_HUANANSFSKPackageFiles Include="$(PkgThingsGateway_Plugin_HUANANSFSK)\Content\net6.0\**\*.*" />
|
||||
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
|
||||
</PropertyGroup>
|
||||
<Message Text="将插件复制到插件目录 $(PluginFolder)" Importance="high" />
|
||||
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MqttYINGKEPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
|
||||
</PropertyGroup>
|
||||
<Message Text="将插件复制到插件目录 $(PluginFolder)" Importance="high" />
|
||||
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HUANANSFSKPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MqttYINGKEPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_HUANANSFSKPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_YPSFSKPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
<Project>
|
||||
<!--插件隔离-->
|
||||
|
||||
|
||||
|
||||
<Target Name="PostPublish" AfterTargets="Publish">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<PluginsFiles Include="bin\$(Configuration)\$(TargetFramework)\Plugins\**" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
<Copy SourceFiles="@(PluginsFiles)" DestinationFolder="$(PublishDir)Plugins\%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ItemGroup>
|
||||
<!--Modbus 插件-->
|
||||
<PackageReference Include="ThingsGateway.Plugin.Modbus" Version="$(PluginVersion)" GeneratePathProperty="true">
|
||||
<Private>false</Private>
|
||||
@@ -100,21 +87,21 @@
|
||||
<PkgThingsGateway_Plugin_VariableExpressionPackageFiles Include="$(PkgThingsGateway_Plugin_VariableExpression)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
|
||||
<PluginFolder>$(TargetDir)GatewayPlugins\</PluginFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(PluginFolder)" />
|
||||
<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_OpcDaNetApiPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcUaPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_RabbitMQPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_VariableExpressionPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_ModbusPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Modbus%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_SiemensS7PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.SiemensS7%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_Dlt645PackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Dlt645%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_DBPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.DB%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_KafkaPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Kafka%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_MqttPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.Mqtt%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcDaPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.OpcDa%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcDaNetApiPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.OpcDaNetApi%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcUaPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.OpcUa%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_RabbitMQPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.RabbitMQ%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_VariableExpressionPackageFiles)" DestinationFolder="$(PluginFolder)ThingsGateway.Plugin.VariableExpression%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
113
src/ThingsGateway.Server/targets/PluginContext.targets
Normal file
113
src/ThingsGateway.Server/targets/PluginContext.targets
Normal file
@@ -0,0 +1,113 @@
|
||||
<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>
|
||||
<!--OpcDa 插件-->
|
||||
<PackageReference Include="ThingsGateway.Plugin.OpcDaNetApi" 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>
|
||||
|
||||
<!--VariableExpression 插件-->
|
||||
<PackageReference Include="ThingsGateway.Plugin.VariableExpression" Version="$(PluginVersion)" GeneratePathProperty="true">
|
||||
<Private>false</Private>
|
||||
<IncludeAssets> native;</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyPluginNugetPackages" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<!-- setting up the variable for convenience -->
|
||||
<PkgThingsGateway_Plugin_ModbusPackageFiles Include="$(PkgThingsGateway_Plugin_Modbus)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_SiemensS7PackageFiles Include="$(PkgThingsGateway_Plugin_SiemensS7)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_Dlt645PackageFiles Include="$(PkgThingsGateway_Plugin_Dlt645)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_DBPackageFiles Include="$(PkgThingsGateway_Plugin_DB)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_KafkaPackageFiles Include="$(PkgThingsGateway_Plugin_Kafka)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_MqttPackageFiles Include="$(PkgThingsGateway_Plugin_Mqtt)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_OpcDaPackageFiles Include="$(PkgThingsGateway_Plugin_OpcDa)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_OpcDaNetApiPackageFiles Include="$(PkgThingsGateway_Plugin_OpcDaNetApi)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
|
||||
|
||||
<PkgThingsGateway_Plugin_OpcUaPackageFiles Include="$(PkgThingsGateway_Plugin_OpcUa)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_RabbitMQPackageFiles Include="$(PkgThingsGateway_Plugin_RabbitMQ)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
<PkgThingsGateway_Plugin_VariableExpressionPackageFiles Include="$(PkgThingsGateway_Plugin_VariableExpression)\Content\$(CustomTargetFramework)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<PluginFolder>$(TargetDir)Plugins\</PluginFolder>
|
||||
<GatewayPluginFolder>$(TargetDir)GatewayPlugins\</GatewayPluginFolder>
|
||||
</PropertyGroup>
|
||||
<RemoveDir Directories="$(PluginFolder)" />
|
||||
<RemoveDir Directories="$(GatewayPluginFolder)" />
|
||||
|
||||
<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_OpcDaNetApiPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_OpcUaPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_RabbitMQPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(PkgThingsGateway_Plugin_VariableExpressionPackageFiles)" DestinationFolder="$(PluginFolder)%(RecursiveDir)" />
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
</Project>
|
||||
19
src/ThingsGateway.Server/targets/Publish1.targets
Normal file
19
src/ThingsGateway.Server/targets/Publish1.targets
Normal file
@@ -0,0 +1,19 @@
|
||||
<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>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,119 +1,118 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Admin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Plugin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\CustomPlugin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Custom.targets" />
|
||||
<PropertyGroup>
|
||||
<CustomTargetFramework>net9.0</CustomTargetFramework>
|
||||
<TargetFrameworks>net9.0-windows;</TargetFrameworks>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<TargetFrameworks>net9.0-windows;</TargetFrameworks>
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<!--<Import Project="..\ThingsGateway.Server\targets\Admin.targets" />-->
|
||||
<Import Project="..\ThingsGateway.Server\targets\PluginContext.targets" />
|
||||
<!--<Import Project="..\ThingsGateway.Server\targets\Plugin.targets" />-->
|
||||
<Import Project="..\ThingsGateway.Server\targets\CustomPlugin.targets" />
|
||||
<Import Project="..\ThingsGateway.Server\targets\Custom.targets" />
|
||||
<PropertyGroup>
|
||||
<CustomTargetFramework>net9.0</CustomTargetFramework>
|
||||
<TargetFrameworks>net9.0-windows;</TargetFrameworks>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
|
||||
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<TargetFrameworks>net9.0-windows;</TargetFrameworks>
|
||||
|
||||
<!--动态适用GC-->
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
<!--使用工作站GC-->
|
||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
<!--动态适用GC-->
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
<!--使用工作站GC-->
|
||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.WindowsForms" Version="9.0.12" />
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.WindowsForms" Version="9.0.21" />
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net6.0' ">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net8.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndex.razor" Link="Index\GatewayIndex.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndex.razor.cs" Link="Index\GatewayIndex.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor" Link="Layout\MainLayout.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\MainLayout.razor.cs" Link="Layout\MainLayout.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor.css" Link="Layout\MainLayout.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\AccessDenied.razor" Link="Layout\AccessDenied.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\AccessDenied.razor.cs" Link="Layout\AccessDenied.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor" Link="Layout\Login.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\Login.razor.cs" Link="Layout\Login.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor.css" Link="Layout\Login.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\NotFound404.razor" Link="Layout\NotFound404.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\NotFound404.razor.cs" Link="Layout\NotFound404.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor" Link="Index\GatewayIndexComponent.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor.cs" Link="Index\GatewayIndexComponent.razor.cs" />
|
||||
<!--安装服务守护-->
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<Compile Include="..\ThingsGateway.Server\Program\SingleFilePublish.cs" Link="Program\SingleFilePublish.cs" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="..\Gateway\ThingsGateway.Gateway.Razor\ThingsGateway.Gateway.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.ico" Link="wwwroot\favicon.ico" />
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.png" Link="wwwroot\favicon.png" />
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.Development.json" Link="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.json" Link="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<ItemGroup>
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndex.razor" Link="Index\GatewayIndex.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndex.razor.cs" Link="Index\GatewayIndex.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor" Link="Layout\MainLayout.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\MainLayout.razor.cs" Link="Layout\MainLayout.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\MainLayout.razor.css" Link="Layout\MainLayout.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\AccessDenied.razor" Link="Layout\AccessDenied.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\AccessDenied.razor.cs" Link="Layout\AccessDenied.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor" Link="Layout\Login.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\Login.razor.cs" Link="Layout\Login.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\Login.razor.css" Link="Layout\Login.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Layout\NotFound404.razor" Link="Layout\NotFound404.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Layout\NotFound404.razor.cs" Link="Layout\NotFound404.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor" Link="Index\GatewayIndexComponent.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor.cs" Link="Index\GatewayIndexComponent.razor.cs" />
|
||||
|
||||
<Content Include="..\ThingsGateway.Server\Configuration\*" LinkBase="Configuration">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Compile Include="..\ThingsGateway.Server\Program\SingleFilePublish.cs" Link="Program\SingleFilePublish.cs" />
|
||||
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\en-US.json" Link="Locales\en-US.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-CN.json" Link="Locales\zh-CN.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-TW.json">
|
||||
<Link>Locales\zh-TW.json</Link>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\ThingsGateway.Photino\Startup.cs" Link="Startup.cs" />
|
||||
<Compile Include="..\ThingsGateway.Photino\Services\*" LinkBase="Services">
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.ico" Link="wwwroot\favicon.ico" />
|
||||
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.png" Link="wwwroot\favicon.png" />
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.Development.json" Link="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\ThingsGateway.Server\appsettings.json" Link="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<Content Include="..\ThingsGateway.Server\Configuration\*" LinkBase="Configuration">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\en-US.json" Link="Locales\en-US.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-CN.json" Link="Locales\zh-CN.json" />
|
||||
<EmbeddedResource Include="..\ThingsGateway.Server\Locales\zh-TW.json">
|
||||
<Link>Locales\zh-TW.json</Link>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Locales\*.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\ThingsGateway.Photino\Startup.cs" Link="Startup.cs" />
|
||||
<Compile Include="..\ThingsGateway.Photino\Services\*" LinkBase="Services">
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{0B748352
|
||||
Directory.Build.props = Directory.Build.props
|
||||
FoundationVersion.props = FoundationVersion.props
|
||||
Version.props = Version.props
|
||||
..\git_pull.bat = ..\git_pull.bat
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gateway", "Gateway", "{5948EA23-4B42-4C22-A266-2E0AE5FA575F}"
|
||||
@@ -34,6 +35,29 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Gateway.Razor
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Foundation.Razor", "Foundation\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj", "{569F229F-FB10-4789-B00B-D9D12383177A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Admin", "Admin", "{72C65578-92A5-4E99-9779-27835B12B32F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Admin.Application", "..\Admin\src\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{C4C01993-DB12-49D9-BDDB-C312042A6C29}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Admin.Razor", "..\Admin\src\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj", "{BC3AE9E7-7B56-4894-9514-52A493A0D724}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Core", "..\Admin\src\ThingsGateway.Core\ThingsGateway.Core.csproj", "{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Furion", "..\Admin\src\ThingsGateway.Furion\ThingsGateway.Furion.csproj", "{3759E861-BA1E-498A-85CF-48A0BE6B00BB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.NewLife.X", "..\Admin\src\ThingsGateway.NewLife.X\ThingsGateway.NewLife.X.csproj", "{42928B73-237A-4483-935E-E7FAAC52F288}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.Razor", "..\Admin\src\ThingsGateway.Razor\ThingsGateway.Razor.csproj", "{015DD6B7-325F-45B5-B69E-CBD62DC6235A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThingsGateway.AdminServer", "..\Admin\src\ThingsGateway.AdminServer\ThingsGateway.AdminServer.csproj", "{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{568A28E1-6CAE-461C-8578-C28BEAC81945}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
..\Admin\src\Admin.props = ..\Admin\src\Admin.props
|
||||
..\Admin\src\PackNuget.props = ..\Admin\src\PackNuget.props
|
||||
..\Admin\src\Version.props = ..\Admin\src\Version.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -80,6 +104,34 @@ Global
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -92,10 +144,18 @@ Global
|
||||
{A1163B55-31D8-4F58-872F-1DD5E0F14490} = {5948EA23-4B42-4C22-A266-2E0AE5FA575F}
|
||||
{6B92AF2D-0997-4887-B1C5-31861F298238} = {5948EA23-4B42-4C22-A266-2E0AE5FA575F}
|
||||
{569F229F-FB10-4789-B00B-D9D12383177A} = {2AC600BB-4325-4E0A-93A7-B1F53C8E2CA7}
|
||||
{C4C01993-DB12-49D9-BDDB-C312042A6C29} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{BC3AE9E7-7B56-4894-9514-52A493A0D724} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{D473E69E-FDBE-4A8E-A835-7F380C8E6D86} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{3759E861-BA1E-498A-85CF-48A0BE6B00BB} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{42928B73-237A-4483-935E-E7FAAC52F288} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{015DD6B7-325F-45B5-B69E-CBD62DC6235A} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{BE13F278-C153-4CB8-A4EF-59BEFAE54CF8} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
{568A28E1-6CAE-461C-8578-C28BEAC81945} = {72C65578-92A5-4E99-9779-27835B12B32F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {199B1B96-4F56-4828-9531-813BA02DB282}
|
||||
RESX_Rules = {"EnabledRules":[]}
|
||||
RESX_NeutralResourcesLanguage = zh-Hans
|
||||
SolutionGuid = {199B1B96-4F56-4828-9531-813BA02DB282}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
26
src/ThingsGatewayRelease.sln
Normal file
26
src/ThingsGatewayRelease.sln
Normal file
@@ -0,0 +1,26 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34622.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Server", "ThingsGateway.Server\ThingsGateway.Server.csproj", "{22875EFB-DADF-4612-A572-33BCC092F644}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{22875EFB-DADF-4612-A572-33BCC092F644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{22875EFB-DADF-4612-A572-33BCC092F644}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{22875EFB-DADF-4612-A572-33BCC092F644}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{22875EFB-DADF-4612-A572-33BCC092F644}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {199B1B96-4F56-4828-9531-813BA02DB282}
|
||||
RESX_Rules = {"EnabledRules":[]}
|
||||
RESX_NeutralResourcesLanguage = zh-Hans
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>7.2.0.60</Version>
|
||||
<Version>7.2.3.12</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user