Compare commits

...

5 Commits

Author SHA1 Message Date
2248356998 qq.com
2e00e8c135 更新依赖 2025-09-08 08:46:52 +08:00
2248356998 qq.com
34dd2cf0a7 更新依赖 2025-09-07 21:52:41 +08:00
2248356998 qq.com
8404e20c5e build: 10.11.27
refactor: 更新依赖
2025-09-06 23:34:32 +08:00
2248356998 qq.com
662aa162e9 fix: sugar无实体curd 2025-09-05 13:16:18 +08:00
2248356998 qq.com
5927738c32 10.11.25 2025-09-05 11:30:33 +08:00
35 changed files with 479 additions and 210 deletions

View File

@@ -738,7 +738,7 @@ namespace ThingsGateway.SqlSugar
.Where(it => it.Name == "Insertable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name.StartsWith("IReadOnlyCollection")))
.Where(it => it.Name == "Insertable");
;
var method = methods.Single().MakeGenericMethod(newList.GetType().GetGenericArguments().First());
InsertMethodInfo result = new InsertMethodInfo()
{
@@ -751,11 +751,11 @@ namespace ThingsGateway.SqlSugar
else
{
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Insertable")
.Where(it => it.Name == "InsertableT" || it.Name == "Insertable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"))
.Where(it => it.Name == "Insertable");
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"));
var method = methods.Single().MakeGenericMethod(singleEntityObjectOrListObject.GetType());
InsertMethodInfo result = new InsertMethodInfo()
{
Context = this.Context,
@@ -826,8 +826,7 @@ namespace ThingsGateway.SqlSugar
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Deleteable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.Name != "pkValue" && z.ParameterType.Name.StartsWith("IReadOnlyCollection")))
.Where(it => it.Name == "Deleteable");
.Where(it => it.GetParameters().Any(z => z.Name != "pkValue" && z.ParameterType.Name.StartsWith("IReadOnlyCollection")));
var method = methods.FirstOrDefault().MakeGenericMethod(newList.GetType().GetGenericArguments().FirstOrDefault());
DeleteMethodInfo result = new DeleteMethodInfo()
{
@@ -840,10 +839,9 @@ namespace ThingsGateway.SqlSugar
else
{
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Deleteable")
.Where(it => it.Name == "Deleteable" || it.Name == "DeleteableT")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"))
.Where(it => it.Name == "Deleteable");
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"));
var method = methods.Single().MakeGenericMethod(singleEntityObjectOrListObject.GetType());
DeleteMethodInfo result = new DeleteMethodInfo()
{
@@ -911,8 +909,7 @@ namespace ThingsGateway.SqlSugar
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Updateable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name.StartsWith("IReadOnlyCollection")))
.Where(it => it.Name == "Updateable");
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name.StartsWith("IReadOnlyCollection")));
var method = methods.Single().MakeGenericMethod(newList.GetType().GetGenericArguments().First());
UpdateMethodInfo result = new UpdateMethodInfo()
{
@@ -925,10 +922,9 @@ namespace ThingsGateway.SqlSugar
else
{
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Updateable")
.Where(it => it.Name == "UpdateableT" || it.Name == "Updateable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"))
.Where(it => it.Name == "Updateable");
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"));
var method = methods.Single().MakeGenericMethod(singleEntityObjectOrListObject.GetType());
UpdateMethodInfo result = new UpdateMethodInfo()
{
@@ -943,10 +939,9 @@ namespace ThingsGateway.SqlSugar
{
UpdateExpressionMethodInfo result = new UpdateExpressionMethodInfo();
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Updateable")
.Where(it => it.Name == "UpdateableT" || it.Name == "Updateable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Length == 0)
.Where(it => it.Name == "Updateable");
.Where(it => it.GetParameters().Length == 0);
var method = methods.Single().MakeGenericMethod(entityType);
result.Context = this.Context;
result.MethodInfo = method;
@@ -1109,8 +1104,7 @@ namespace ThingsGateway.SqlSugar
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Storageable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name.StartsWith("IEnumerable")))
.Where(it => it.Name == "Storageable");
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name.StartsWith("IEnumerable")));
var method = methods.Single().MakeGenericMethod(newList.GetType().GetGenericArguments().First());
StorageableMethodInfo result = new StorageableMethodInfo()
{
@@ -1123,10 +1117,9 @@ namespace ThingsGateway.SqlSugar
else
{
var methods = this.Context.GetType().GetMethods()
.Where(it => it.Name == "Storageable")
.Where(it => it.Name == "StorageableT" || it.Name == "Storageable")
.Where(it => it.GetGenericArguments().Length != 0)
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"))
.Where(it => it.Name == "Storageable");
.Where(it => it.GetParameters().Any(z => z.ParameterType.Name == "T"));
var method = methods.Single().MakeGenericMethod(singleEntityObjectOrList.GetType());
StorageableMethodInfo result = new StorageableMethodInfo()
{

View File

@@ -24,13 +24,13 @@
<ItemGroup>
<PackageReference Include="SqlSugarCore.Dm" Version="8.8.2" />
<PackageReference Include="SqlSugarCore.Kdbndp" Version="9.3.7.821" />
<PackageReference Include="SqlSugarCore.Kdbndp" Version="9.3.7.905" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" />
<!--<PackageReference Include="Microsoft.Data.Sqlite" Version="$(NET9Version)" />-->
<PackageReference Include="MySqlConnector" Version="2.4.0" />
<PackageReference Include="Npgsql" Version="9.0.3" />
<PackageReference Include="CsvHelper" Version="33.1.0" />
<PackageReference Include="TDengine.Connector" Version="3.1.8" />
<PackageReference Include="TDengine.Connector" Version="3.1.9" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.9.1" />
<PackageReference Include="Oscar.Data.SqlClient" Version="4.2.23" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />

View File

@@ -1,9 +1,9 @@
<Project>
<PropertyGroup>
<PluginVersion>10.11.24</PluginVersion>
<ProPluginVersion>10.11.24</ProPluginVersion>
<DefaultVersion>10.11.24</DefaultVersion>
<PluginVersion>10.11.29</PluginVersion>
<ProPluginVersion>10.11.29</ProPluginVersion>
<DefaultVersion>10.11.29</DefaultVersion>
<AuthenticationVersion>10.11.3</AuthenticationVersion>
<SourceGeneratorVersion>10.11.3</SourceGeneratorVersion>
<NET8Version>8.0.19</NET8Version>

View File

@@ -49,12 +49,11 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
this.ThrowIfDisposed();
this.ThrowIfClientNotConnected();
if (!await this.OnTcpSending(memory).ConfigureAwait(false)) return;
var transport = this.Transport;
var adapter = this.DataHandlingAdapter;
var locker = transport.SemaphoreSlimForWriter;
var locker = transport.WriteLocker;
await locker.WaitAsync(token).ConfigureAwait(false);
try
@@ -62,7 +61,7 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
// 如果数据处理适配器未设置,则使用默认发送方式。
if (adapter == null)
{
await transport.Output.WriteAsync(memory, token).ConfigureAwait(false);
await transport.Writer.WriteAsync(memory, token).ConfigureAwait(false);
}
else
{
@@ -70,7 +69,7 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
var ddpSend = new DDPSend(memory, Id, true);
ddpSend.Build(ref byteBlock);
var newMemory = byteBlock.Memory;
var writer = new PipeBytesWriter(transport.Output);
var writer = new PipeBytesWriter(transport.Writer);
adapter.SendInput(ref writer, in newMemory);
await writer.FlushAsync(token).ConfigureAwait(false);
}
@@ -100,7 +99,7 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
var transport = this.Transport;
var adapter = this.DataHandlingAdapter;
var locker = transport.SemaphoreSlimForWriter;
var locker = transport.WriteLocker;
await locker.WaitAsync(token).ConfigureAwait(false);
try
@@ -113,7 +112,7 @@ public class DDPTcpSessionClientChannel : TcpSessionClientChannel
requestInfoBuilder.Build(ref byteBlock);
var ddpSend = new DDPSend(byteBlock.Memory, Id, true);
var writer = new PipeBytesWriter(transport.Output);
var writer = new PipeBytesWriter(transport.Writer);
adapter.SendInput(ref writer, ddpSend);
await writer.FlushAsync(token).ConfigureAwait(false);
}

View File

@@ -15,7 +15,7 @@ namespace ThingsGateway.Foundation;
/// <summary>
/// 终端通道
/// </summary>
public interface IClientChannel : IChannel, ISender, IClient, IClientSender, IOnlineClient
public interface IClientChannel : IChannel, ISender, IClient, IClientSender, IOnlineClient, IDependencyClient
{
/// <summary>
/// 当前通道的数据处理适配器

View File

@@ -34,7 +34,26 @@ public static class PluginUtil
if (channelOptions.ChannelType == ChannelTypeEnum.TcpClient)
{
action += a => a.UseReconnection<ITcpClient>();
action += a => a.UseReconnection<IClientChannel>().SetActionForCheck((channel, failCount) =>
{
if (channel.Online)
{
return Task.FromResult(ConnectionCheckResult.Alive);
}
else
{
if (failCount > 1)
{
return Task.FromResult(ConnectionCheckResult.Dead);
}
return Task.FromResult(ConnectionCheckResult.Skip);
}
})
.SetPollingTick(TimeSpan.FromSeconds(5)
);
}
return action;
}

View File

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

View File

@@ -3,7 +3,7 @@
<Import Project="..\..\PackNuget.props" />
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>

View File

@@ -48,18 +48,6 @@ public class ControlController : ControllerBase, IRpcServer
App.CacheService.Clear();
}
/// <summary>
/// 删除通道/设备缓存
/// </summary>
/// <returns></returns>
[HttpPost("removeCache")]
[DisplayName("删除通道/设备缓存")]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public void RemoveCache()
{
App.GetService<IDeviceService>().DeleteDeviceFromCache();
App.GetService<IChannelService>().DeleteChannelFromCache();
}
/// <summary>
/// 控制设备线程暂停
@@ -226,6 +214,17 @@ public class ControlController : ControllerBase, IRpcServer
return GlobalData.VariableRuntimeService.InsertTestDataAsync(testVariableCount, testDeviceCount, slaveUrl, businessEnable, restart);
}
/// <summary>
/// 增加测试Dtu数据
/// </summary>
[HttpPost("insertTestDtuData")]
[DisplayName("增加测试Dtu数据")]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task InsertTestDtuDataAsync(int testDeviceCount, string slaveUrl, bool restart = true)
{
return GlobalData.VariableRuntimeService.InsertTestDtuDataAsync(testDeviceCount, slaveUrl, restart);
}
/// <summary>
/// 确认实时报警
/// </summary>

View File

@@ -77,7 +77,7 @@ public partial class ManagementController : ControllerBase, IRpcServer
App.GetService<IDevicePageService>().ClearDeviceAsync(restart);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task ClearRulesAsync() => App.GetService<IRulesService>().ClearRulesAsync();
public Task ClearRulesAsync() => App.GetService<IRulesPageService>().ClearRulesAsync();
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task<bool> ClearVariableAsync(bool restart) =>
@@ -140,7 +140,7 @@ public partial class ManagementController : ControllerBase, IRpcServer
public Task DeleteRuleRuntimesAsync(List<long> ids) => App.GetService<IRulesEngineHostedService>().DeleteRuleRuntimesAsync(ids);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task<bool> DeleteRulesAsync(List<long> ids) => App.GetService<IRulesService>().DeleteRulesAsync(ids);
public Task<bool> DeleteRulesAsync(List<long> ids) => App.GetService<IRulesPageService>().DeleteRulesAsync(ids);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
@@ -200,13 +200,6 @@ public partial class ManagementController : ControllerBase, IRpcServer
public Task<List<Variable>> GetVariableListAsync([FromBody] GetListRequest<QueryPageOptions> request) =>
App.GetService<IVariablePageService>().GetVariableListAsync(request.Options, request.Max);
[HttpGet]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Get)]
public Task<List<Rules>> GetAllRulesAsync() => App.GetService<IRulesService>().GetAllRulesAsync();
[HttpGet]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Get)]
public Task<string> GetChannelNameAsync(long id) =>
@@ -345,6 +338,14 @@ public partial class ManagementController : ControllerBase, IRpcServer
public Task InsertTestDataAsync([FromBody] InsertTestDataInput input) =>
App.GetService<IVariablePageService>().InsertTestDataAsync(input.TestVariableCount, input.TestDeviceCount, input.SlaveUrl, input.BusinessEnable, input.Restart);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task InsertTestDtuDataAsync([FromBody] InsertTestDtuDataInput input) =>
App.GetService<IVariablePageService>().InsertTestDtuDataAsync(input.TestDeviceCount, input.SlaveUrl, input.Restart);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task<bool> IsRedundantDeviceAsync(long id) =>
@@ -458,7 +459,7 @@ public partial class ManagementController : ControllerBase, IRpcServer
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task<QueryData<Rules>> RulesPageAsync([FromBody] KVQueryPageOptions option) =>
App.GetService<IRulesService>().RulesPageAsync(option.Options, option.FilterKeyValueAction);
App.GetService<IRulesPageService>().RulesPageAsync(option.Options, option.FilterKeyValueAction);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
@@ -478,7 +479,7 @@ public partial class ManagementController : ControllerBase, IRpcServer
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
public Task<bool> SaveRulesAsync([FromBody] Rules input, ItemChangedType type) =>
App.GetService<IRulesService>().SaveRulesAsync(input, type);
App.GetService<IRulesPageService>().SaveRulesAsync(input, type);
[HttpPost]
[TouchSocket.WebApi.WebApi(Method = TouchSocket.WebApi.HttpMethodType.Post)]
@@ -635,7 +636,12 @@ public class InsertTestDataInput
public bool BusinessEnable { get; set; }
public bool Restart { get; set; }
}
public class InsertTestDtuDataInput
{
public int TestDeviceCount { get; set; }
public string SlaveUrl { get; set; }
public bool Restart { get; set; }
}
public class LastLogDataInput
{
public string File { get; set; }

View File

@@ -61,7 +61,7 @@ public class LogJob : IJob
//网关通道日志以通道id命名
var rulesService = App.RootServices.GetService<IRulesService>();
var ruleNames = (await rulesService.GetAllRulesAsync().ConfigureAwait(false)).Select(a => a.Name.ToString()).ToHashSet();
var ruleNames = (await rulesService.GetFromDBAsync(a => a.Name.ToString()).ConfigureAwait(false)).ToHashSet();
var ruleBaseDir = RulesEngineHostedService.LogDir;
Directory.CreateDirectory(ruleBaseDir);

View File

@@ -58,9 +58,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteChannelFromCache();
App.GetService<IDeviceService>().DeleteDeviceFromCache();
App.GetService<IVariableService>().DeleteVariableCache();
return true;
}
else
@@ -87,9 +85,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteChannelFromCache();
App.GetService<IDeviceService>().DeleteDeviceFromCache();
App.GetService<IVariableService>().DeleteVariableCache();
return true;
}
else
@@ -124,9 +120,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteChannelFromCache();
App.GetService<IDeviceService>().DeleteDeviceFromCache();
App.GetService<IVariableService>().DeleteVariableCache();
return true;
}
else
@@ -149,7 +143,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteChannelFromCache();
}
else
{
@@ -181,7 +175,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteChannelFromCache();
return true;
}
else
@@ -214,7 +208,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteChannelFromCache();
return true;
}
else
@@ -224,11 +218,6 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
}
}
/// <inheritdoc />
public void DeleteChannelFromCache()
{
//App.CacheService.Remove(ThingsGatewayCacheConst.Cache_Channel);//删除通道缓存
}
@@ -299,7 +288,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
DeleteChannelFromCache();
return true;
}
return false;
@@ -320,7 +309,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
DeleteChannelFromCache();
return true;
}
return false;
@@ -404,7 +393,7 @@ internal sealed class ChannelService : BaseService<Channel>, IChannelService
await db.BulkUpdateAsync(upData, 200000).ConfigureAwait(false);
}
DeleteChannelFromCache();
return upData.Select(a => a.Id).Concat(insertData.Select(a => a.Id)).ToHashSet();
}

View File

@@ -38,11 +38,6 @@ internal interface IChannelService
/// <param name="ids">待删除通道的ID列表</param>
Task<bool> DeleteChannelAsync(IEnumerable<long> ids);
/// <summary>
/// 从缓存中删除通道
/// </summary>
void DeleteChannelFromCache();
/// <summary>
/// 导出通道为文件流结果
/// </summary>

View File

@@ -63,8 +63,6 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteDeviceFromCache();
App.GetService<IVariableService>().DeleteVariableCache();
return true;
}
else
@@ -87,7 +85,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteDeviceFromCache();
}
else
{
@@ -112,8 +110,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
.WhereIf(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.ToList();
var result = (await db.Updateable(data).UpdateColumns(differences.Select(a => a.Key).ToArray()).ExecuteCommandAsync().ConfigureAwait(false)) > 0;
if (result)
DeleteDeviceFromCache();
return result;
}
else
@@ -141,7 +138,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteDeviceFromCache();
}
else
{
@@ -169,7 +166,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
DeleteDeviceFromCache();
return true;
}
else
@@ -179,12 +176,6 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
}
}
/// <inheritdoc />
public void DeleteDeviceFromCache()
{
//App.CacheService.Remove(ThingsGatewayCacheConst.Cache_Device);//删除设备缓存
}
/// <summary>
/// 从缓存/数据库获取全部信息
/// </summary>
@@ -274,7 +265,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
DeleteDeviceFromCache();
return true;
}
return false;
@@ -290,7 +281,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
DeleteDeviceFromCache();
return true;
}
return false;
@@ -400,7 +391,7 @@ internal sealed class DeviceService : BaseService<Device>, IDeviceService
await db.BulkCopyAsync(insertData, 200000).ConfigureAwait(false);
await db.BulkUpdateAsync(upData, 200000).ConfigureAwait(false);
}
DeleteDeviceFromCache();
return upData.Select(a => a.Id).Concat(insertData.Select(a => a.Id)).ToHashSet();
}

View File

@@ -51,10 +51,6 @@ internal interface IDeviceService
/// <returns>删除是否成功的异步任务</returns>
Task<bool> DeleteDeviceAsync(IEnumerable<long> ids);
/// <summary>
/// 删除设备缓存信息。
/// </summary>
void DeleteDeviceFromCache();
/// <summary>
/// 导出设备信息到文件流。

View File

@@ -134,12 +134,6 @@ public interface IManagementRpcServer : IRpcServer
[DmtpRpc]
Task<string> ExportVariableFileAsync(GatewayExportFilter exportFilter);
/// <summary>
/// 从缓存/数据库获取全部信息
/// </summary>
/// <returns>规则列表</returns>
[DmtpRpc]
Task<List<Rules>> GetAllRulesAsync();
[DmtpRpc]
Task<List<Channel>> GetChannelListAsync(QueryPageOptions options, int max = 0);
@@ -227,7 +221,8 @@ public interface IManagementRpcServer : IRpcServer
[DmtpRpc]
Task InsertTestDataAsync(int testVariableCount, int testDeviceCount, string slaveUrl, bool businessEnable, bool restart);
[DmtpRpc]
Task InsertTestDtuDataAsync(int testDeviceCount, string slaveUrl, bool restart);
[DmtpRpc]
Task<bool> IsRedundantDeviceAsync(long id);
@@ -287,6 +282,8 @@ public interface IManagementRpcServer : IRpcServer
[DmtpRpc]
Task RestartDeviceAsync(long id, bool deleteCache);
[DmtpRpc]
Task RestartRuleRuntimeAsync();
[DmtpRpc]
Task RestartServerAsync();

View File

@@ -48,7 +48,7 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task<bool> ClearDeviceAsync(bool restart) =>
App.GetService<IDevicePageService>().ClearDeviceAsync(restart);
public Task ClearRulesAsync() => App.GetService<IRulesService>().ClearRulesAsync();
public Task ClearRulesAsync() => App.GetService<IRulesPageService>().ClearRulesAsync();
public Task<bool> ClearVariableAsync(bool restart) =>
App.GetService<IVariablePageService>().ClearVariableAsync(restart);
@@ -75,7 +75,7 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task DeleteRuleRuntimesAsync(List<long> ids) => App.GetService<IRulesEngineHostedService>().DeleteRuleRuntimesAsync(ids);
public Task<bool> DeleteRulesAsync(List<long> ids) => App.GetService<IRulesService>().DeleteRulesAsync(ids);
public Task<bool> DeleteRulesAsync(List<long> ids) => App.GetService<IRulesPageService>().DeleteRulesAsync(ids);
public Task<bool> DeleteVariableAsync(List<long> ids, bool restart) =>
App.GetService<IVariablePageService>().DeleteVariableAsync(ids, restart);
@@ -107,8 +107,6 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task<string> ExportVariableFileAsync(GatewayExportFilter exportFilter) => App.GetService<IVariablePageService>().ExportVariableFileAsync(exportFilter);
public Task<List<Rules>> GetAllRulesAsync() => App.GetService<IRulesService>().GetAllRulesAsync();
public Task<List<Channel>> GetChannelListAsync(QueryPageOptions options, int max = 0) =>
App.GetService<IChannelPageService>().GetChannelListAsync(options, max);
@@ -181,6 +179,10 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task InsertTestDataAsync(int testVariableCount, int testDeviceCount, string slaveUrl, bool businessEnable, bool restart) =>
App.GetService<IVariablePageService>().InsertTestDataAsync(testVariableCount, testDeviceCount, slaveUrl, businessEnable, restart);
public Task InsertTestDtuDataAsync(int testDeviceCount, string slaveUrl, bool restart) =>
App.GetService<IVariablePageService>().InsertTestDtuDataAsync(testDeviceCount, slaveUrl, restart);
public Task<bool> IsRedundantDeviceAsync(long id) =>
App.GetService<IDevicePageService>().IsRedundantDeviceAsync(id);
@@ -244,7 +246,7 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task<string> RulesLogPathAsync(long rulesId) => App.GetService<IRulesEngineHostedService>().RulesLogPathAsync(rulesId);
public Task<QueryData<Rules>> RulesPageAsync(QueryPageOptions option, FilterKeyValueAction filterKeyValueAction = null) => App.GetService<IRulesService>().RulesPageAsync(option, filterKeyValueAction);
public Task<QueryData<Rules>> RulesPageAsync(QueryPageOptions option, FilterKeyValueAction filterKeyValueAction = null) => App.GetService<IRulesPageService>().RulesPageAsync(option, filterKeyValueAction);
public Task<bool> SaveChannelAsync(Channel input, ItemChangedType type, bool restart) =>
App.GetService<IChannelPageService>().SaveChannelAsync(input, type, restart);
@@ -254,7 +256,7 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task SavePluginByPathAsync(PluginAddPathInput plugin) => App.GetService<IPluginPageService>().SavePluginByPathAsync(plugin);
public Task<bool> SaveRulesAsync(Rules input, ItemChangedType type) => App.GetService<IRulesService>().SaveRulesAsync(input, type);
public Task<bool> SaveRulesAsync(Rules input, ItemChangedType type) => App.GetService<IRulesPageService>().SaveRulesAsync(input, type);
public Task<bool> SaveVariableAsync(Variable input, ItemChangedType type, bool restart) =>
App.GetService<IVariablePageService>().SaveVariableAsync(input, type, restart);
@@ -284,4 +286,7 @@ public partial class ManagementRpcServer : IRpcServer, IManagementRpcServer, IBa
public Task UnAuthorizeAsync() => App.GetService<IAuthenticationService>().UnAuthorizeAsync();
public Task<string> UUIDAsync() => App.GetService<IAuthenticationService>().UUIDAsync();
public Task RestartRuleRuntimeAsync() => App.GetService<IRulesEngineHostedService>().RestartRuleRuntimeAsync();
}

View File

@@ -93,7 +93,7 @@ public partial class ManagementTask : AsyncDisposableObject
var config = new TouchSocketConfig()
.SetRemoteIPHost(_managementOptions.ServerUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 1024 * 1024 * 1024 })
.SetDmtpOption(new DmtpOption() { VerifyToken = _managementOptions.VerifyToken })
.SetDmtpOption(a => a.VerifyToken = _managementOptions.VerifyToken)
.ConfigureContainer(a =>
{
a.AddDmtpRouteService();//添加路由策略
@@ -134,7 +134,7 @@ public partial class ManagementTask : AsyncDisposableObject
.SetTick(TimeSpan.FromMilliseconds(_managementOptions.HeartbeatInterval))
.SetMaxFailCount(3);
a.AddDmtpHandshakedPlugin(async () =>
a.AddDmtpCreatedChannelPlugin(async () =>
{
try
{
@@ -157,7 +157,7 @@ public partial class ManagementTask : AsyncDisposableObject
var config = new TouchSocketConfig()
.SetListenIPHosts(_managementOptions.ServerUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 1024 * 1024 * 1024 })
.SetDmtpOption(new DmtpOption() { VerifyToken = _managementOptions.VerifyToken })
.SetDmtpOption(a => a.VerifyToken = _managementOptions.VerifyToken)
.ConfigureContainer(a =>
{
a.AddDmtpRouteService();//添加路由策略

View File

@@ -332,7 +332,7 @@ internal sealed class RedundancyTask : IRpcDriver, IAsyncDisposable
var config = new TouchSocketConfig()
.SetRemoteIPHost(redundancy.MasterUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 0x20000000 })
.SetDmtpOption(new DmtpOption() { VerifyToken = redundancy.VerifyToken })
.SetDmtpOption(a => a.VerifyToken = redundancy.VerifyToken)
.ConfigureContainer(a =>
{
a.AddLogger(LogMessage);
@@ -377,7 +377,7 @@ internal sealed class RedundancyTask : IRpcDriver, IAsyncDisposable
var config = new TouchSocketConfig()
.SetListenIPHosts(redundancy.MasterUri)
.SetAdapterOption(new AdapterOption() { MaxPackageSize = 0x20000000 })
.SetDmtpOption(new DmtpOption() { VerifyToken = redundancy.VerifyToken })
.SetDmtpOption(a => a.VerifyToken = redundancy.VerifyToken)
.ConfigureContainer(a =>
{
a.AddLogger(LogMessage);

View File

@@ -8,6 +8,7 @@
// QQ群605534569
// ------------------------------------------------------------------------------
namespace ThingsGateway.Gateway.Application;
public interface IRulesEngineHostedService
@@ -18,4 +19,6 @@ public interface IRulesEngineHostedService
Task<Rules> GetRuleRuntimesAsync(long rulesId);
Task DeleteRuleRuntimesAsync(List<long> ids);
Task EditRuleRuntimesAsync(Rules rules);
Task RestartRuleRuntimeAsync();
}

View File

@@ -10,9 +10,11 @@
using BootstrapBlazor.Components;
using System.Linq.Expressions;
namespace ThingsGateway.Gateway.Application;
public interface IRulesService
public interface IRulesPageService
{
/// <summary>
/// 清除所有规则
@@ -25,12 +27,6 @@ public interface IRulesService
/// <param name="ids">待删除规则的ID列表</param>
Task<bool> DeleteRulesAsync(List<long> ids);
/// <summary>
/// 从缓存/数据库获取全部信息
/// </summary>
/// <returns>规则列表</returns>
Task<List<Rules>> GetAllRulesAsync();
/// <summary>
/// 报表查询
/// </summary>
@@ -45,3 +41,13 @@ public interface IRulesService
/// <param name="type">保存类型</param>
Task<bool> SaveRulesAsync(Rules input, ItemChangedType type);
}
public interface IRulesService : IRulesPageService
{
/// <summary>
/// 从缓存/数据库获取全部信息
/// </summary>
/// <returns>规则列表</returns>
Task<List<TResult>> GetFromDBAsync<TResult>(Expression<Func<Rules, TResult>> slct, Expression<Func<Rules, bool>> expression = null, SqlSugarClient db = null);
}

View File

@@ -234,13 +234,31 @@ internal sealed class RulesEngineHostedService : BackgroundService, IRulesEngine
{
await Task.Yield();
await RestartRuleRuntimeAsync().ConfigureAwait(false);
while (!cancellationToken.IsCancellationRequested)
{
foreach (var item in Diagrams?.Values?.SelectMany(a => a.Nodes) ?? new List<NodeModel>())
{
if (item is IExexcuteExpressionsBase)
{
CSharpScriptEngineExtension.SetExpire((item as TextNode).Text);
}
}
await Task.Delay(60000, cancellationToken).ConfigureAwait(false);
}
}
public async Task RestartRuleRuntimeAsync()
{
try
{
await RestartLock.WaitAsync(cancellationToken).ConfigureAwait(false); // 等待获取锁,以确保只有一个线程可以执行以下代码
TokenSource ??= new CancellationTokenSource();
await RestartLock.WaitAsync().ConfigureAwait(false);
Cancel();
Clear();
TokenSource ??= new CancellationTokenSource();
Rules = await App.GetService<IRulesService>().GetAllRulesAsync().ConfigureAwait(false);
Rules = await App.GetService<IRulesService>().GetFromDBAsync(a => a).ConfigureAwait(false);
Diagrams = new();
foreach (var rules in Rules.Where(a => a.Status))
{
@@ -259,18 +277,6 @@ internal sealed class RulesEngineHostedService : BackgroundService, IRulesEngine
{
RestartLock.Release(); // 释放锁
}
while (!cancellationToken.IsCancellationRequested)
{
foreach (var item in Diagrams?.Values?.SelectMany(a => a.Nodes) ?? new List<NodeModel>())
{
if (item is IExexcuteExpressionsBase)
{
CSharpScriptEngineExtension.SetExpire((item as TextNode).Text);
}
}
await Task.Delay(60000, cancellationToken).ConfigureAwait(false);
}
}
public override async Task StopAsync(CancellationToken cancellationToken)

View File

@@ -10,9 +10,7 @@
using BootstrapBlazor.Components;
using System.Data;
using ThingsGateway.Extension.Generic;
using System.Linq.Expressions;
using TouchSocket.Core;
@@ -38,15 +36,12 @@ internal sealed class RulesService : BaseService<Rules>, IRulesService
var dataScope = await GlobalData.SysUserService.GetCurrentUserDataScopeAsync().ConfigureAwait(false);
using var db = GetDB();
var ids = await db.Queryable<Rules>().WhereIF(dataScope != null && dataScope?.Count > 0, u => dataScope.Contains(u.CreateOrgId))//在指定机构列表查询
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.Select(a => a.Id).ToListAsync().ConfigureAwait(false);
await db.Deleteable<Rules>(a => ids.Contains(a.Id)).ExecuteCommandAsync().ConfigureAwait(false);
var data = (await GetAllRulesAsync().ConfigureAwait(false))
.WhereIf(dataScope != null && dataScope?.Count > 0, u => dataScope.Contains(u.CreateOrgId))//在指定机构列表查询
.WhereIf(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.Select(a => a.Id).ToList();
await db.Deleteable<Rules>(a => data.Contains(a.Id)).ExecuteCommandAsync().ConfigureAwait(false);
DeleteRulesFromCache();
await RulesEngineHostedService.DeleteRuleRuntimesAsync(data).ConfigureAwait(false);
await RulesEngineHostedService.DeleteRuleRuntimesAsync(ids).ConfigureAwait(false);
}
[OperDesc("DeleteRules", localizerType: typeof(Rules))]
@@ -60,30 +55,20 @@ internal sealed class RulesService : BaseService<Rules>, IRulesService
.ExecuteCommandAsync().ConfigureAwait(false);
DeleteRulesFromCache();
await RulesEngineHostedService.DeleteRuleRuntimesAsync(ids).ConfigureAwait(false);
return true;
}
private const string cacheKey = "ThingsGateway:Cache_RulesEngines:List";
/// <inheritdoc />
public void DeleteRulesFromCache()
{
App.CacheService.Remove(cacheKey);//删除通道缓存
}
/// <summary>
/// 从缓存/数据库获取全部信息
/// </summary>
/// <returns>列表</returns>
public async Task<List<Rules>> GetAllRulesAsync()
public async Task<List<TResult>> GetFromDBAsync<TResult>(Expression<Func<Rules, TResult>> slct, Expression<Func<Rules, bool>> expression = null, SqlSugarClient db = null)
{
var channels = App.CacheService.Get<List<Rules>>(cacheKey);
if (channels == null)
{
using var db = GetDB();
channels = await db.Queryable<Rules>().ToListAsync().ConfigureAwait(false);
App.CacheService.Set(cacheKey, channels);
}
db ??= GetDB();
var channels = await db.Queryable<Rules>().WhereIF(expression != null, expression).OrderBy(a => a.Id).Select(slct).ToListAsync().ConfigureAwait(false);
return channels;
}
@@ -117,7 +102,6 @@ internal sealed class RulesService : BaseService<Rules>, IRulesService
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
DeleteRulesFromCache();
await RulesEngineHostedService.EditRuleRuntimesAsync(input).ConfigureAwait(false);
return true;
}

View File

@@ -35,5 +35,6 @@ namespace ThingsGateway.Gateway.Application
Task<OperResult<object>> OnWriteVariableAsync(long id, string writeData);
Task<Dictionary<string, ImportPreviewOutputBase>> ImportVariableAsync(IBrowserFile a, bool restart);
Task<Dictionary<string, ImportPreviewOutputBase>> ImportVariableFileAsync(string filePath, bool restart);
Task InsertTestDtuDataAsync(int deviceCount, string slaveUrl, bool restart);
}
}

View File

@@ -106,10 +106,10 @@ internal interface IVariableService
Task UpdateInitValueAsync(List<Variable> variables);
Task<List<Variable>> GetByDeviceIdAsync(List<long> deviceIds);
void DeleteVariableCache();
ImportPreviewOutput<Dictionary<string, Variable>> SetVariableData(HashSet<long>? dataScope, IReadOnlyDictionary<string, DeviceRuntime> deviceDicts, Dictionary<string, ImportPreviewOutputBase> ImportPreviews, ImportPreviewOutput<Dictionary<string, Variable>> deviceImportPreview, Dictionary<string, PluginInfo> driverPluginNameDict, ConcurrentDictionary<string, (Type, Dictionary<string, PropertyInfo>, Dictionary<string, PropertyInfo>)> propertysDict, string sheetName, IEnumerable<IDictionary<string, object>> rows);
List<VariableRuntime> GetAllVariableRuntime();
Task<Dictionary<string, ImportPreviewOutputBase>> PreviewAsync(string filePath);
Task<HashSet<long>> ImportVariableAsync(List<Variable> upData, List<Variable> insertData);
Task<Dictionary<string, ImportPreviewOutputBase>> PreviewAsync(IFormFile browserFile);
Task<(List<Channel>, List<Device>, List<Variable>)> InsertTestDtuDataAsync(int deviceCount, string slaveUrl = "127.0.0.1:502");
}

View File

@@ -423,6 +423,45 @@ public class VariableRuntimeService : IVariableRuntimeService
}
}
public async Task InsertTestDtuDataAsync(int deviceCount, string slaveUrl, bool restart)
{
try
{
// await WaitLock.WaitAsync().ConfigureAwait(false);
var datas = await GlobalData.VariableService.InsertTestDtuDataAsync(deviceCount, slaveUrl).ConfigureAwait(false);
{
var newChannelRuntimes = datas.Item1.AdaptListChannelRuntime();
//批量修改之后,需要重新加载通道
RuntimeServiceHelper.Init(newChannelRuntimes);
{
var newDeviceRuntimes = datas.Item2.AdaptListDeviceRuntime();
RuntimeServiceHelper.Init(newDeviceRuntimes);
}
{
var newVariableRuntimes = datas.Item3.AdaptListVariableRuntime();
RuntimeServiceHelper.Init(newVariableRuntimes);
}
//根据条件重启通道线程
if (restart)
{
await GlobalData.ChannelThreadManage.RestartChannelAsync(newChannelRuntimes).ConfigureAwait(false);
await RuntimeServiceHelper.ChangedDriverAsync(_logger).ConfigureAwait(false);
}
}
}
finally
{
//WaitLock.Release();
}
}
public Task<Dictionary<string, ImportPreviewOutputBase>> PreviewAsync(IBrowserFile browserFile)
{
return GlobalData.VariableService.PreviewAsync(browserFile);

View File

@@ -226,9 +226,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
_channelService.DeleteChannelFromCache();//刷新缓存
_deviceService.DeleteDeviceFromCache();
DeleteVariableCache();
}
else
{
@@ -237,6 +235,144 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
return (newChannels, newDevices, newVariables);
}
public async Task<(List<Channel>, List<Device>, List<Variable>)> InsertTestDtuDataAsync(int deviceCount, string slaveUrl = "127.0.0.1:502")
{
if (slaveUrl.IsNullOrWhiteSpace()) slaveUrl = "127.0.0.1:502";
List<Channel> newChannels = new();
List<Device> newDevices = new();
List<Variable> newVariables = new();
ManageHelper.CheckChannelCount(deviceCount);
ManageHelper.CheckDeviceCount(deviceCount);
ManageHelper.CheckVariableCount(deviceCount);
//DTU
for (int i = 0; i < deviceCount; i++)
{
Channel serviceChannel = new Channel();
Device serviceDevice = new Device();
{
var id = CommonUtils.GetSingleId();
var name = $"modbusSlaveChannel{id}";
serviceChannel.ChannelType = ChannelTypeEnum.TcpClient;
serviceChannel.Name = name;
serviceChannel.Enable = true;
serviceChannel.Id = id;
serviceChannel.CreateUserId = UserManager.UserId;
serviceChannel.CreateOrgId = UserManager.OrgId;
serviceChannel.RemoteUrl = "127.0.0.1:502";
serviceChannel.DtuId = name;
serviceChannel.Heartbeat = "ThingsGateway.Plugin.Modbus";
serviceChannel.PluginName = "ThingsGateway.Plugin.Modbus.ModbusSlave";
newChannels.Add(serviceChannel);
}
{
var id = CommonUtils.GetSingleId();
var name = $"modbusSlaveDevice{id}";
serviceDevice.Name = name;
serviceDevice.Id = id;
serviceDevice.CreateUserId = UserManager.UserId;
serviceDevice.CreateOrgId = UserManager.OrgId;
serviceDevice.ChannelId = serviceChannel.Id;
serviceDevice.IntervalTime = "1000";
newDevices.Add(serviceDevice);
}
}
//SERVICE
var dtuids = newChannels.Select(a => a.Name).ToList();
Channel channel = new Channel();
{
var id = CommonUtils.GetSingleId();
var name = $"modbusChannel{id}";
channel.ChannelType = ChannelTypeEnum.TcpService;
channel.Name = name;
channel.Id = id;
channel.CreateUserId = UserManager.UserId;
channel.CreateOrgId = UserManager.OrgId;
channel.BindUrl = slaveUrl;
channel.Heartbeat = "ThingsGateway.Plugin.Modbus";
channel.PluginName = "ThingsGateway.Plugin.Modbus.ModbusMaster";
//动态插件属性默认
newChannels.Add(channel);
}
foreach (var item in dtuids)
{
Device device = new Device();
{
var id = CommonUtils.GetSingleId();
var name = $"modbusDevice{id}";
device.Name = name;
device.Id = id;
device.ChannelId = channel.Id;
device.CreateUserId = UserManager.UserId;
device.CreateOrgId = UserManager.OrgId;
device.IntervalTime = "1000";
device.DevicePropertys = new Dictionary<string, string>()
{
{
nameof(CollectFoundationDtuPackPropertyBase.DtuId),item
}
};
//动态插件属性默认
newDevices.Add(device);
}
{
var address = $"400001";
var id = CommonUtils.GetSingleId();
var name = $"modbus{address}";
Variable variable = new Variable();
variable.DataType = DataTypeEnum.Int16;
variable.Name = name;
variable.Id = id;
variable.CreateOrgId = UserManager.OrgId;
variable.CreateUserId = UserManager.UserId;
variable.DeviceId = device.Id;
variable.RegisterAddress = address;
newVariables.Add(variable);
}
}
using var db = GetDB();
var result = await db.UseTranAsync(async () =>
{
if (GlobalData.HardwareJob.HardwareInfo.MachineInfo.AvailableMemory < 2 * 1024 * 1024 || WebEnableVariable.WebEnable == false)
{
await db.BulkCopyAsync(newChannels, 10000).ConfigureAwait(false);
await db.BulkCopyAsync(newDevices, 10000).ConfigureAwait(false);
await db.BulkCopyAsync(newVariables, 10000).ConfigureAwait(false);
}
else
{
await db.BulkCopyAsync(newChannels, 200000).ConfigureAwait(false);
await db.BulkCopyAsync(newDevices, 200000).ConfigureAwait(false);
await db.BulkCopyAsync(newVariables, 200000).ConfigureAwait(false);
}
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
}
else
{
throw new(result.ErrorMessage, result.ErrorException);
}
return (newChannels, newDevices, newVariables);
}
#endregion
/// <summary>
@@ -265,7 +401,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
if (result > 0)
{
DeleteVariableCache();
return true;
}
}
@@ -277,7 +413,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
if (result > 0)
{
DeleteVariableCache();
return true;
}
}
@@ -300,8 +436,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
.ToList();
var result = (await db.Updateable(data).UpdateColumns(differences.Select(a => a.Key).ToArray()).ExecuteCommandAsync().ConfigureAwait(false)) > 0;
if (result)
DeleteVariableCache();
return result;
}
else
@@ -320,8 +455,6 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.ExecuteCommandAsync().ConfigureAwait(false);
if (result > 0)
DeleteVariableCache();
}
[OperDesc("DeleteVariable", isRecordPar: false, localizerType: typeof(Variable))]
@@ -335,8 +468,6 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.ExecuteCommandAsync().ConfigureAwait(false)) > 0;
if (result)
DeleteVariableCache();
return result;
}
@@ -441,16 +572,13 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
DeleteVariableCache();
return true;
}
return false;
}
public void DeleteVariableCache()
{
//App.CacheService.Remove(ThingsGatewayCacheConst.Cache_Variable);
}
public List<VariableRuntime> GetAllVariableRuntime()
{
@@ -579,7 +707,7 @@ internal sealed class VariableService : BaseService<Variable>, IVariableService
await db.BulkCopyAsync(insertData, 200000).ConfigureAwait(false);
await db.BulkUpdateAsync(upData, 200000).ConfigureAwait(false);
}
DeleteVariableCache();
return upData.Select(a => a.Id).Concat(insertData.Select(a => a.Id)).ToHashSet();
}

View File

@@ -25,6 +25,7 @@ public class Startup : AppStartup
#region R
services.AddSingleton<IRulesService, RulesService>();
services.AddSingleton<IRulesPageService>(a => a.GetService<IRulesService>());
services.AddGatewayHostedService<IRulesEngineHostedService, RulesEngineHostedService>();
#endregion

View File

@@ -11,9 +11,9 @@
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
<PackageReference Include="Rougamo.Fody" Version="5.0.1" />
<PackageReference Include="System.Linq.Async" Version="6.0.3" />
<PackageReference Include="TouchSocket.Dmtp" Version="4.0.0-beta.13" />
<!--<PackageReference Include="TouchSocket.WebApi.Swagger" Version="4.0.0-beta.13" />-->
<PackageReference Include="TouchSocket.WebApi" Version="4.0.0-beta.13" />
<PackageReference Include="TouchSocket.Dmtp" Version="4.0.0-beta.25" />
<!--<PackageReference Include="TouchSocket.WebApi.Swagger" Version="4.0.0-beta.25" />-->
<PackageReference Include="TouchSocket.WebApi" Version="4.0.0-beta.25" />
<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />
<!--<ProjectReference Include="..\..\PluginPro\ThingsGateway.Authentication\ThingsGateway.Authentication.csproj" />-->

View File

@@ -243,6 +243,7 @@
"BusinessEnable": "BusinessEnable",
"SlaveUrl": "SlaveUrl",
"Test": "Addition of test variables",
"TestDtu": "Addition of test dtu variables",
"TestDeviceCount": "TestDeviceCount",
"TestVariableCount": "TestVariableCount",
"WriteValue": "WriteValue",

View File

@@ -243,6 +243,7 @@
"BusinessEnable": "添加业务设备",
"SlaveUrl": "服务端Url",
"Test": "一键添加测试变量",
"TestDtu": "一键添加Dtu测试变量",
"TestDeviceCount": "采集设备数量",
"TestVariableCount": "变量数量",
"WriteValue": "写入值",

View File

@@ -127,7 +127,7 @@
@if (WebsiteOption.Value.Demo || App.HostEnvironment.IsDevelopment())
{
<PopConfirmButton Color=Color.Warning Text="@Localizer["Test"]" IsKeepDisabled=@(!AuthorizeButton(AdminOperConst.Add))
IsAsync OnConfirm=@(InsertTestDataAsync)>
IsAsync OnConfirm=@(InsertTestDataAsync) class="me-1">
<BodyTemplate>
<BootstrapInput @bind-Value=TestVariableCount ShowLabel="true" ShowLabelTooltip="true" />
@@ -136,6 +136,16 @@
</BodyTemplate>
</PopConfirmButton>
<PopConfirmButton Color=Color.Warning Text="@Localizer["TestDtu"]" IsKeepDisabled=@(!AuthorizeButton(AdminOperConst.Add))
IsAsync OnConfirm=@(InsertTestDtuDataAsync)>
<BodyTemplate>
<BootstrapInput @bind-Value=TestDeviceCount ShowLabel="true" ShowLabelTooltip="true" />
</BodyTemplate>
</PopConfirmButton>
}
</TableToolbarTemplate>

View File

@@ -481,6 +481,32 @@ finally
}
}
private async Task InsertTestDtuDataAsync()
{
try
{
try
{
await Task.Run(() => VariablePageService.InsertTestDtuDataAsync(TestDeviceCount, SlaveUrl, AutoRestartThread));
}
finally
{
await InvokeAsync(async () =>
{
await ToastService.Default();
await table.QueryAsync();
StateHasChanged();
});
}
}
catch (Exception ex)
{
await InvokeAsync(async () => await ToastService.Warn(ex));
}
}
[Parameter]
public bool AutoRestartThread { get; set; }

View File

@@ -23,7 +23,7 @@ public partial class RulesPage : ThingsGatewayModuleComponentBase
{
[Inject]
[NotNull]
private IRulesService? RulesService { get; set; }
private IRulesPageService? RulesService { get; set; }
protected override async Task InvokeInitAsync()

View File

@@ -10,6 +10,7 @@
using System.Buffers;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using TouchSocket.Sockets;
@@ -184,10 +185,28 @@ public class ModbusSlave : DeviceBase, IModbusAddress
/// <inheritdoc/>
private void Init(ModbusRequest mAddress)
{
//自动扩容
ModbusServer01ByteBlocks.GetOrAdd(mAddress.Station, a =>
{
var bytes = new ByteBlock(ushort.MaxValue * 2);
bytes.SetLength(ushort.MaxValue * 2);
var bytes = new ByteBlock(256,
(c) =>
{
var data = ArrayPool<byte>.Shared.Rent(c);
for (int i = 0; i < data.Length; i++)
{
data[i] = 0;
}
return data;
},
(m) =>
{
if (MemoryMarshal.TryGetArray((ReadOnlyMemory<byte>)m, out var result))
{
ArrayPool<byte>.Shared.Return(result.Array);
}
}
);
bytes.SetLength(256);
for (int i = 0; i < bytes.Length; i++)
{
bytes.WriteByte(0);
@@ -197,8 +216,25 @@ public class ModbusSlave : DeviceBase, IModbusAddress
});
ModbusServer02ByteBlocks.GetOrAdd(mAddress.Station, a =>
{
var bytes = new ByteBlock(ushort.MaxValue * 2);
bytes.SetLength(ushort.MaxValue * 2);
var bytes = new ByteBlock(256,
(c) =>
{
var data = ArrayPool<byte>.Shared.Rent(c);
for (int i = 0; i < data.Length; i++)
{
data[i] = 0;
}
return data;
},
(m) =>
{
if (MemoryMarshal.TryGetArray((ReadOnlyMemory<byte>)m, out var result))
{
ArrayPool<byte>.Shared.Return(result.Array);
}
}
);
bytes.SetLength(256);
for (int i = 0; i < bytes.Length; i++)
{
bytes.WriteByte(0);
@@ -208,8 +244,25 @@ public class ModbusSlave : DeviceBase, IModbusAddress
});
ModbusServer03ByteBlocks.GetOrAdd(mAddress.Station, a =>
{
var bytes = new ByteBlock(ushort.MaxValue * 2);
bytes.SetLength(ushort.MaxValue * 2);
var bytes = new ByteBlock(256,
(c) =>
{
var data = ArrayPool<byte>.Shared.Rent(c);
for (int i = 0; i < data.Length; i++)
{
data[i] = 0;
}
return data;
},
(m) =>
{
if (MemoryMarshal.TryGetArray((ReadOnlyMemory<byte>)m, out var result))
{
ArrayPool<byte>.Shared.Return(result.Array);
}
}
);
bytes.SetLength(256);
for (int i = 0; i < bytes.Length; i++)
{
bytes.WriteByte(0);
@@ -219,8 +272,25 @@ public class ModbusSlave : DeviceBase, IModbusAddress
});
ModbusServer04ByteBlocks.GetOrAdd(mAddress.Station, a =>
{
var bytes = new ByteBlock(ushort.MaxValue * 2);
bytes.SetLength(ushort.MaxValue * 2);
var bytes = new ByteBlock(256,
(c) =>
{
var data = ArrayPool<byte>.Shared.Rent(c);
for (int i = 0; i < data.Length; i++)
{
data[i] = 0;
}
return data;
},
(m) =>
{
if (MemoryMarshal.TryGetArray((ReadOnlyMemory<byte>)m, out var result))
{
ArrayPool<byte>.Shared.Return(result.Array);
}
}
);
bytes.SetLength(256);
for (int i = 0; i < bytes.Length; i++)
{
bytes.WriteByte(0);
@@ -278,16 +348,20 @@ public class ModbusSlave : DeviceBase, IModbusAddress
switch (f)
{
case 1:
return OperResult.CreateSuccessResult(ModbusServer01ByteBlock.Memory.Slice(mAddress.StartAddress, len));
ModbusServer01ByteBlock.Position = mAddress.StartAddress;
return OperResult.CreateSuccessResult((ReadOnlyMemory<byte>)ModbusServer01ByteBlock.GetMemory(len).Slice(0, len));
case 2:
return OperResult.CreateSuccessResult(ModbusServer02ByteBlock.Memory.Slice(mAddress.StartAddress, len));
ModbusServer02ByteBlock.Position = mAddress.StartAddress;
return OperResult.CreateSuccessResult((ReadOnlyMemory<byte>)ModbusServer02ByteBlock.GetMemory(len).Slice(0, len));
case 3:
return OperResult.CreateSuccessResult(ModbusServer03ByteBlock.Memory.Slice(mAddress.StartAddress * RegisterByteLength, len));
ModbusServer03ByteBlock.Position = mAddress.StartAddress * RegisterByteLength;
return OperResult.CreateSuccessResult((ReadOnlyMemory<byte>)ModbusServer03ByteBlock.GetMemory(len).Slice(0, len));
case 4:
return OperResult.CreateSuccessResult(ModbusServer04ByteBlock.Memory.Slice(mAddress.StartAddress * RegisterByteLength, len));
ModbusServer04ByteBlock.Position = mAddress.StartAddress * RegisterByteLength;
return OperResult.CreateSuccessResult((ReadOnlyMemory<byte>)ModbusServer04ByteBlock.GetMemory(len).Slice(0, len));
}
}
}