feat: 添加保存值功能
This commit is contained in:
		| @@ -122,6 +122,14 @@ public class Variable : PrimaryIdEntity | ||||
|     [AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)] | ||||
|     public virtual bool RpcWriteEnable { get; set; } = true; | ||||
|  | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 保存值 | ||||
|     /// </summary> | ||||
|     [SugarColumn(ColumnDescription = "保存值", IsNullable = true)] | ||||
|     [AutoGenerateColumn(Visible = true, Filterable = true, Sortable = true)] | ||||
|     public virtual bool SaveValue { get; set; } = false; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 变量额外属性Json | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -11,6 +11,8 @@ | ||||
| using Microsoft.Extensions.Localization; | ||||
| using Microsoft.Extensions.Logging; | ||||
|  | ||||
| using Newtonsoft.Json.Linq; | ||||
|  | ||||
| using ThingsGateway.Gateway.Application.Extensions; | ||||
|  | ||||
| using TouchSocket.Core; | ||||
| @@ -194,8 +196,48 @@ public class CollectDeviceHostedService : DeviceHostedService | ||||
|                     { | ||||
|                         // 如果设备已更改,则执行启动前的操作 | ||||
|                         if (isChanged) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 //添加保存数据变量读取操作 | ||||
|                                 var saveVariable = dev.VariableRunTimes.Where(a => a.Value.SaveValue).ToDictionary(a => a.Value.Id, a => a.Value); | ||||
|  | ||||
|                                 if (saveVariable.Any()) | ||||
|                                 { | ||||
|                                     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 | ||||
|                         { | ||||
|                             // 启动新的通道线程 | ||||
| @@ -271,6 +313,8 @@ public class CollectDeviceHostedService : DeviceHostedService | ||||
|                 await CreatAllChannelThreadsAsync().ConfigureAwait(false); | ||||
|                 await OnCollectDeviceStarting().ConfigureAwait(false); | ||||
|             } | ||||
|  | ||||
|             await ReadValue().ConfigureAwait(false); | ||||
|             await StartAllChannelThreadsAsync().ConfigureAwait(false); | ||||
|             await OnCollectDeviceStarted().ConfigureAwait(false); | ||||
|             _ = Task.Run(() => | ||||
| @@ -290,6 +334,52 @@ public class CollectDeviceHostedService : DeviceHostedService | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     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.Any(); | ||||
|                     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.Any()) | ||||
|                 { | ||||
|                     await cacheDb.DBProvider.Deleteable<CacheDBItem<JToken>>(ids).ExecuteCommandAsync().ConfigureAwait(false); | ||||
|                 } | ||||
|                 cacheDb.SafeDispose(); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogWarning(ex, "SaveValue"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 停止 | ||||
|     /// </summary> | ||||
| @@ -305,6 +395,9 @@ public class CollectDeviceHostedService : DeviceHostedService | ||||
|                 await BeforeRemoveAllChannelThreadAsync().ConfigureAwait(false); | ||||
|                 //取消其他后台服务 | ||||
|                 await OnCollectDeviceStoping().ConfigureAwait(false); | ||||
|  | ||||
|                 await SaveValue().ConfigureAwait(false); | ||||
|  | ||||
|                 //停止全部采集线程 | ||||
|                 await RemoveAllChannelThreadAsync(removeDevice).ConfigureAwait(false); | ||||
|                 //停止其他后台服务 | ||||
| @@ -331,6 +424,35 @@ public class CollectDeviceHostedService : DeviceHostedService | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SaveValue() | ||||
|     { | ||||
|         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(); | ||||
|  | ||||
|             if (saveVariable.Any()) | ||||
|             { | ||||
|                 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(); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogWarning(ex, "SaveValue"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 读取数据库,创建全部设备 | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -355,6 +355,7 @@ public abstract class DeviceHostedService : BackgroundService | ||||
|         // 检查是否已请求停止,如果没有则开始每个通道线程 | ||||
|         if (!_stoppingToken.IsCancellationRequested) | ||||
|         { | ||||
|  | ||||
|             foreach (var item in ChannelThreads) | ||||
|             { | ||||
|                 if (!_stoppingToken.IsCancellationRequested) | ||||
|   | ||||
| @@ -92,6 +92,7 @@ | ||||
|     "ReadExpressions": "ReadExpressions", | ||||
|     "WriteExpressions": "WriteExpressions", | ||||
|     "RpcWriteEnable": "RpcWriteEnable", | ||||
|     "SaveValue": "SaveValue", | ||||
|  | ||||
|     "AlarmDelay": "AlarmDelay", | ||||
|     "BoolOpenAlarmEnable": "BoolOpenAlarmEnable", | ||||
| @@ -337,6 +338,7 @@ | ||||
|     "ReadExpressions": "ReadExpressions", | ||||
|     "WriteExpressions": "WriteExpressions", | ||||
|     "RpcWriteEnable": "RpcWriteEnable", | ||||
|     "SaveValue": "SaveValue", | ||||
|     "AlarmDelay": "AlarmDelay", | ||||
|     "BoolOpenAlarmEnable": "BoolOpenAlarmEnable", | ||||
|     "BoolOpenRestrainExpressions": "BoolOpenRestrainExpressions", | ||||
|   | ||||
| @@ -120,6 +120,7 @@ | ||||
|     "ReadExpressions": "读取表达式", | ||||
|     "WriteExpressions": "写入表达式", | ||||
|     "RpcWriteEnable": "远程写入", | ||||
|     "SaveValue": "保存值", | ||||
|  | ||||
|     "AlarmDelay": "报警延时", | ||||
|     "BoolOpenAlarmEnable": "布尔开报警使能", | ||||
| @@ -398,6 +399,7 @@ | ||||
|     "ReadExpressions": "读取表达式", | ||||
|     "WriteExpressions": "写入表达式", | ||||
|     "RpcWriteEnable": "远程写入", | ||||
|     "SaveValue": "保存值", | ||||
|  | ||||
|     "AlarmDelay": "报警延时", | ||||
|     "BoolOpenAlarmEnable": "布尔开报警使能", | ||||
|   | ||||
| @@ -107,6 +107,7 @@ | ||||
|     "ReadExpressions": "讀取表達式", | ||||
|     "WriteExpressions": "寫入表達式", | ||||
|     "RpcWriteEnable": "遠端寫入", | ||||
|     "SaveValue": "保存值", | ||||
|     "AlarmDelay": "警報延遲", | ||||
|     "BoolOpenAlarmEnable": "布林開警報啟用", | ||||
|     "BoolOpenRestrainExpressions": "布林開警報約束", | ||||
| @@ -368,6 +369,7 @@ | ||||
|     "ReadExpressions": "讀取表達式", | ||||
|     "WriteExpressions": "寫入表達式", | ||||
|     "RpcWriteEnable": "遠端寫入", | ||||
|     "SaveValue": "保存值", | ||||
|     "AlarmDelay": "警報延遲", | ||||
|     "BoolOpenAlarmEnable": "布林開警報啟用", | ||||
|     "BoolOpenRestrainExpressions": "布林開警報約束", | ||||
|   | ||||
| @@ -13,6 +13,8 @@ using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.Extensions.Localization; | ||||
| using Microsoft.Extensions.Logging; | ||||
|  | ||||
| using Newtonsoft.Json.Linq; | ||||
|  | ||||
| using System.Collections.Concurrent; | ||||
|  | ||||
| using ThingsGateway.NewLife.X; | ||||
| @@ -356,9 +358,35 @@ public class ChannelThread | ||||
|  | ||||
|             driverBase.AfterStop(); | ||||
|  | ||||
|  | ||||
|             // 如果需要移除的是采集设备 | ||||
|             if (IsCollectChannel) | ||||
|             { | ||||
|                 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(); | ||||
|  | ||||
|                     if (saveVariable.Any()) | ||||
|                     { | ||||
|                         var cacheDb = CacheDBUtil.GetCache(typeof(CacheDBItem<JToken>), nameof(VariableRunTime), nameof(VariableRunTime.SaveValue)); | ||||
|                         var varList = await cacheDb.DBProvider.Storageable(saveVariable).ExecuteCommandAsync().ConfigureAwait(false); | ||||
|  | ||||
|                         cacheDb.SafeDispose(); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     LogMessage.LogWarning(ex, "SaveValue"); | ||||
|                 } | ||||
|  | ||||
|                 driverBase.RemoveCollectDeviceRuntime(); | ||||
|             } | ||||
|             else | ||||
| @@ -501,6 +529,8 @@ public class ChannelThread | ||||
|                 // 如果需要移除的是采集设备 | ||||
|                 if (IsCollectChannel) | ||||
|                 { | ||||
|  | ||||
|  | ||||
|                     DriverBases.RemoveCollectDeviceRuntime(); | ||||
|                 } | ||||
|                 else | ||||
|   | ||||
| @@ -155,6 +155,7 @@ public abstract class CollectBase : DriverBase | ||||
|  | ||||
|     protected override void Dispose(bool disposing) | ||||
|     { | ||||
|  | ||||
|         this.RemoveCollectDeviceRuntime(); | ||||
|         base.Dispose(disposing); | ||||
|     } | ||||
|   | ||||
| @@ -246,6 +246,7 @@ public abstract class DriverBase : DisposableObject | ||||
|  | ||||
|         try | ||||
|         { | ||||
|  | ||||
|             // 如果已经取消了操作,则直接返回 | ||||
|             if (cancellationToken.IsCancellationRequested) | ||||
|             { | ||||
|   | ||||
| @@ -62,7 +62,7 @@ public class VariableService : BaseService<Variable>, IVariableService | ||||
|         List<Device> newDevices = new(); | ||||
|         List<Variable> newVariables = new(); | ||||
|         var addressNum = 1; | ||||
|         var variableCount = 1000; | ||||
|         var variableCount = 10000; | ||||
|         var channelCount = Math.Max(count / variableCount, 1); | ||||
|         for (int i = 0; i < channelCount; i++) | ||||
|         { | ||||
| @@ -90,8 +90,8 @@ public class VariableService : BaseService<Variable>, IVariableService | ||||
|                 //动态插件属性默认 | ||||
|                 newDevices.Add(device); | ||||
|             } | ||||
|             if (channelCount == i + 1 && (count % 1000) != 0) | ||||
|                 variableCount = Math.Min(count % 1000, 1000); | ||||
|             if (channelCount == i + 1 && (count % 10000) != 0) | ||||
|                 variableCount = Math.Min(count % 10000, 10000); | ||||
|             for (int i1 = 0; i1 < variableCount; i1++) | ||||
|             { | ||||
|                 addressNum++; | ||||
| @@ -138,9 +138,9 @@ public class VariableService : BaseService<Variable>, IVariableService | ||||
|  | ||||
|         var result = await db.UseTranAsync(async () => | ||||
|         { | ||||
|             await db.Fastest<Channel>().PageSize(50000).BulkCopyAsync(newChannels).ConfigureAwait(false); | ||||
|             await db.Fastest<Device>().PageSize(50000).BulkCopyAsync(newDevices).ConfigureAwait(false); | ||||
|             await db.Fastest<Variable>().PageSize(50000).BulkCopyAsync(newVariables).ConfigureAwait(false); | ||||
|             await db.Fastest<Channel>().PageSize(100000).BulkCopyAsync(newChannels).ConfigureAwait(false); | ||||
|             await db.Fastest<Device>().PageSize(100000).BulkCopyAsync(newDevices).ConfigureAwait(false); | ||||
|             await db.Fastest<Variable>().PageSize(100000).BulkCopyAsync(newVariables).ConfigureAwait(false); | ||||
|         }).ConfigureAwait(false); | ||||
|         if (result.IsSuccess)//如果成功了 | ||||
|         { | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
|                         <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"> | ||||
| @@ -141,6 +142,7 @@ else | ||||
|                     <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"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Diego
					Diego