Compare commits
	
		
			5 Commits
		
	
	
		
			10.12.17.0
			...
			10.12.24.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 694437c7d5 | ||
|   | 0e78cdefe7 | ||
|   | 087dc9aaa3 | ||
|   | dacf255f1a | ||
|   | e3960ce115 | 
							
								
								
									
										43
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -1,4 +1,7 @@ | ||||
| # ThingsGateway | ||||
|  | ||||
| <p align="center"> | ||||
| <img src="logo.svg" width = "400" height = "200" alt="The name of the image" align=center /> | ||||
| </p> | ||||
|  | ||||
| [](https://gitee.com/ThingsGateway/ThingsGateway/stargazers)  | ||||
| [](https://github.com/ThingsGateway/ThingsGateway) | ||||
| @@ -11,31 +14,31 @@ | ||||
| </a> | ||||
|  | ||||
| ## Introduction | ||||
|  | ||||
|  | ||||
| A cross-platform, high-performance edge data collection gateway based on net8/10. | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Documentation | ||||
|  | ||||
|  | ||||
|  | ||||
| [Documentation](https://thingsgateway.cn/). | ||||
|  | ||||
|  | ||||
| [NuGet](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Demo | ||||
|  | ||||
|  | ||||
|  | ||||
| [Demo](https://demo.thingsgateway.cn/) | ||||
|  | ||||
|  | ||||
|  | ||||
| Account: **SuperAdmin** | ||||
|  | ||||
|  | ||||
|  | ||||
| Password: **111111** | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Docker | ||||
|  | ||||
| @@ -50,7 +53,7 @@ docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway_arm64 | ||||
|  | ||||
| ### Plugin List | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #### Data Collection Plugins | ||||
|  | ||||
| @@ -80,28 +83,28 @@ docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway_arm64 | ||||
| | TDengineDB       | Time-series database storage                                                                      | | ||||
| | QuestDB          | Time-series database storage                                                                      | | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## License | ||||
|  | ||||
|  | ||||
|  | ||||
| [License](https://thingsgateway.cn/docs/1) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Sponsorship | ||||
|  | ||||
|  | ||||
|  | ||||
| [Sponsorship Approach](https://thingsgateway.cn/docs/1000) | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Community | ||||
|  | ||||
|  | ||||
|  | ||||
| QQ Group: 605534569 [Jump](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=NnBjPO-8kcNFzo_RzSbdICflb97u2O1i&authKey=V1MI3iJtpDMHc08myszP262kDykbx2Yev6ebE4Me0elTe0P0IFAmtU5l7Sy5w0jx&noverify=0&group_code=605534569) | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Pro Plugins | ||||
|  | ||||
|  | ||||
|  | ||||
| [Plugin List](https://thingsgateway.cn/docs/1001) | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| # ThingsGateway | ||||
|  | ||||
| <p align="center"> | ||||
| <img src="logo.svg" width = "400" height = "200" alt="The name of the image" align=center /> | ||||
| </p> | ||||
|  | ||||
| [](https://gitee.com/ThingsGateway/ThingsGateway/stargazers)  | ||||
| [](https://github.com/ThingsGateway/ThingsGateway) | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								icon.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
							
								
								
									
										
											BIN
										
									
								
								icon.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 177 KiB | 
							
								
								
									
										9
									
								
								logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 236 KiB | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 177 KiB | 
| @@ -0,0 +1,134 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| //  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充 | ||||
| //  此代码版权(除特别声明外的代码)归作者本人Diego所有 | ||||
| //  源代码使用协议遵循本仓库的开源协议及附加协议 | ||||
| //  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway | ||||
| //  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway | ||||
| //  使用文档:https://thingsgateway.cn/ | ||||
| //  QQ群:605534569 | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| namespace ThingsGateway.Common; | ||||
|  | ||||
| /// <inheritdoc/> | ||||
| [ThingsGateway.DependencyInjection.SuppressSniffer] | ||||
| public static class EnumerableQueryPageOptionsExtensions | ||||
| { | ||||
|     public static IEnumerable<T> GetData<T>(this IEnumerable<T> datas, QueryPageOptions option, out int totalCount, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         totalCount = 0; | ||||
|         if (datas == null) | ||||
|             return new List<T>(); | ||||
|         where ??= option.ToFilter(); | ||||
|         if (where.HasFilters()) | ||||
|         { | ||||
|             datas = datas.Where(where.GetFilterFunc<T>());//name asc模式 | ||||
|         } | ||||
|  | ||||
|         if (option.SortList.Count > 0) | ||||
|         { | ||||
|             datas = datas.Sort(option.SortList);//name asc模式 | ||||
|         } | ||||
|         if (option.AdvancedSortList.Count > 0) | ||||
|         { | ||||
|             datas = datas.Sort(option.AdvancedSortList);//name asc模式 | ||||
|         } | ||||
|         if (option.SortOrder != SortOrder.Unset && !option.SortName.IsNullOrWhiteSpace()) | ||||
|         { | ||||
|             datas = datas.Sort(option.SortName, option.SortOrder); | ||||
|         } | ||||
|  | ||||
|         totalCount = datas.Count(); | ||||
|  | ||||
|         if (option.IsPage) | ||||
|         { | ||||
|             datas = datas.Skip((option.PageIndex - 1) * option.PageItems).Take(option.PageItems); | ||||
|         } | ||||
|         else if (option.IsVirtualScroll) | ||||
|         { | ||||
|             datas = datas.Skip((option.StartIndex) * option.PageItems).Take(option.PageItems); | ||||
|         } | ||||
|         return datas; | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     public static IEnumerable<T> GetQuery<T>(this IEnumerable<T> query, QueryPageOptions option, Func<IEnumerable<T>, IEnumerable<T>>? queryFunc = null, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         if (queryFunc != null) | ||||
|             query = queryFunc(query); | ||||
|         where ??= option.ToFilter(); | ||||
|  | ||||
|         if (where.HasFilters()) | ||||
|         { | ||||
|             query = query.Where(where.GetFilterFunc<T>());//name asc模式 | ||||
|         } | ||||
|  | ||||
|         if (option.SortOrder != SortOrder.Unset && !string.IsNullOrEmpty(option.SortName)) | ||||
|         { | ||||
|             var invoker = Utility.GetSortFunc<T>(); | ||||
|             query = invoker(query, option.SortName, option.SortOrder); | ||||
|         } | ||||
|         else if (option.SortList.Count > 0) | ||||
|         { | ||||
|             var invoker = Utility.GetSortListFunc<T>(); | ||||
|             query = invoker(query, option.SortList); | ||||
|         } | ||||
|         else if (option.AdvancedSortList.Count > 0) | ||||
|         { | ||||
|             var invoker = Utility.GetSortListFunc<T>(); | ||||
|             query = invoker(query, option.AdvancedSortList); | ||||
|         } | ||||
|         return query; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 根据查询条件返回QueryData | ||||
|     /// </summary> | ||||
|     public static QueryData<T> GetQueryData<T>(this IEnumerable<T> datas, QueryPageOptions option, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         var ret = new QueryData<T>() | ||||
|         { | ||||
|             IsSorted = option.SortOrder != SortOrder.Unset, | ||||
|             IsFiltered = option.Filters.Count > 0, | ||||
|             IsAdvanceSearch = option.AdvanceSearches.Count > 0 || option.CustomerSearches.Count > 0, | ||||
|             IsSearch = option.Searches.Count > 0 | ||||
|         }; | ||||
|         var items = datas.GetData(option, out var totalCount, where); | ||||
|         ret.TotalCount = totalCount; | ||||
|  | ||||
|         if (totalCount > 0) | ||||
|         { | ||||
|             if (!items.Any() && option.PageIndex != 1) | ||||
|             { | ||||
|                 option.PageIndex = 1; | ||||
|                 items = datas.GetData(option, out totalCount, where); | ||||
|             } | ||||
|         } | ||||
|         ret.Items = items.ToList(); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 根据查询条件返回QueryData | ||||
|     /// </summary> | ||||
|     public static QueryData<SelectedItem> GetQueryData<T>(this IEnumerable<T> datas, VirtualizeQueryOption option, Func<IEnumerable<T>, IEnumerable<SelectedItem>> func, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         var ret = new QueryData<SelectedItem>() | ||||
|         { | ||||
|             IsSorted = false, | ||||
|             IsFiltered = false, | ||||
|             IsAdvanceSearch = false, | ||||
|             IsSearch = !option.SearchText.IsNullOrWhiteSpace() | ||||
|         }; | ||||
|  | ||||
|         var items = datas.Skip((option.StartIndex)).Take(option.Count); | ||||
|         ret.TotalCount = datas.Count(); | ||||
|  | ||||
|         ret.Items = func(items).ToList(); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -19,7 +19,7 @@ using System.Reflection; | ||||
| 
 | ||||
| using ThingsGateway.Common.Extension; | ||||
| 
 | ||||
| namespace ThingsGateway.DB; | ||||
| namespace ThingsGateway.Common; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// 导出excel扩展 | ||||
| @@ -11,7 +11,7 @@ | ||||
| using Microsoft.AspNetCore.Components.Forms; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| 
 | ||||
| namespace ThingsGateway.DB; | ||||
| namespace ThingsGateway.Common; | ||||
| 
 | ||||
| /// <inheritdoc/> | ||||
| [ThingsGateway.DependencyInjection.SuppressSniffer] | ||||
| @@ -10,7 +10,7 @@ | ||||
| 
 | ||||
| using Yitter.IdGenerator; | ||||
| 
 | ||||
| namespace ThingsGateway.DB; | ||||
| namespace ThingsGateway.Common; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// 公共功能 | ||||
| @@ -16,74 +16,6 @@ namespace ThingsGateway.DB; | ||||
| [ThingsGateway.DependencyInjection.SuppressSniffer] | ||||
| public static class QueryPageOptionsExtensions | ||||
| { | ||||
|     public static IEnumerable<T> GetData<T>(this IEnumerable<T> datas, QueryPageOptions option, out int totalCount, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         totalCount = 0; | ||||
|         if (datas == null) | ||||
|             return new List<T>(); | ||||
|         where ??= option.ToFilter(); | ||||
|         if (where.HasFilters()) | ||||
|         { | ||||
|             datas = datas.Where(where.GetFilterFunc<T>());//name asc模式 | ||||
|         } | ||||
|  | ||||
|         if (option.SortList.Count > 0) | ||||
|         { | ||||
|             datas = datas.Sort(option.SortList);//name asc模式 | ||||
|         } | ||||
|         if (option.AdvancedSortList.Count > 0) | ||||
|         { | ||||
|             datas = datas.Sort(option.AdvancedSortList);//name asc模式 | ||||
|         } | ||||
|         if (option.SortOrder != SortOrder.Unset && !option.SortName.IsNullOrWhiteSpace()) | ||||
|         { | ||||
|             datas = datas.Sort(option.SortName, option.SortOrder); | ||||
|         } | ||||
|  | ||||
|         totalCount = datas.Count(); | ||||
|  | ||||
|         if (option.IsPage) | ||||
|         { | ||||
|             datas = datas.Skip((option.PageIndex - 1) * option.PageItems).Take(option.PageItems); | ||||
|         } | ||||
|         else if (option.IsVirtualScroll) | ||||
|         { | ||||
|             datas = datas.Skip((option.StartIndex) * option.PageItems).Take(option.PageItems); | ||||
|         } | ||||
|         return datas; | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     public static IEnumerable<T> GetQuery<T>(this IEnumerable<T> query, QueryPageOptions option, Func<IEnumerable<T>, IEnumerable<T>>? queryFunc = null, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         if (queryFunc != null) | ||||
|             query = queryFunc(query); | ||||
|         where ??= option.ToFilter(); | ||||
|  | ||||
|         if (where.HasFilters()) | ||||
|         { | ||||
|             query = query.Where(where.GetFilterFunc<T>());//name asc模式 | ||||
|         } | ||||
|  | ||||
|         if (option.SortOrder != SortOrder.Unset && !string.IsNullOrEmpty(option.SortName)) | ||||
|         { | ||||
|             var invoker = Utility.GetSortFunc<T>(); | ||||
|             query = invoker(query, option.SortName, option.SortOrder); | ||||
|         } | ||||
|         else if (option.SortList.Count > 0) | ||||
|         { | ||||
|             var invoker = Utility.GetSortListFunc<T>(); | ||||
|             query = invoker(query, option.SortList); | ||||
|         } | ||||
|         else if (option.AdvancedSortList.Count > 0) | ||||
|         { | ||||
|             var invoker = Utility.GetSortListFunc<T>(); | ||||
|             query = invoker(query, option.AdvancedSortList); | ||||
|         } | ||||
|         return query; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 根据查询条件返回sqlsugar ISugarQueryable | ||||
|     /// </summary> | ||||
| @@ -111,50 +43,4 @@ public static class QueryPageOptionsExtensions | ||||
|         return query; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 根据查询条件返回QueryData | ||||
|     /// </summary> | ||||
|     public static QueryData<T> GetQueryData<T>(this IEnumerable<T> datas, QueryPageOptions option, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         var ret = new QueryData<T>() | ||||
|         { | ||||
|             IsSorted = option.SortOrder != SortOrder.Unset, | ||||
|             IsFiltered = option.Filters.Count > 0, | ||||
|             IsAdvanceSearch = option.AdvanceSearches.Count > 0 || option.CustomerSearches.Count > 0, | ||||
|             IsSearch = option.Searches.Count > 0 | ||||
|         }; | ||||
|         var items = datas.GetData(option, out var totalCount, where); | ||||
|         ret.TotalCount = totalCount; | ||||
|  | ||||
|         if (totalCount > 0) | ||||
|         { | ||||
|             if (!items.Any() && option.PageIndex != 1) | ||||
|             { | ||||
|                 option.PageIndex = 1; | ||||
|                 items = datas.GetData(option, out totalCount, where); | ||||
|             } | ||||
|         } | ||||
|         ret.Items = items.ToList(); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 根据查询条件返回QueryData | ||||
|     /// </summary> | ||||
|     public static QueryData<SelectedItem> GetQueryData<T>(this IEnumerable<T> datas, VirtualizeQueryOption option, Func<IEnumerable<T>, IEnumerable<SelectedItem>> func, FilterKeyValueAction where = null) | ||||
|     { | ||||
|         var ret = new QueryData<SelectedItem>() | ||||
|         { | ||||
|             IsSorted = false, | ||||
|             IsFiltered = false, | ||||
|             IsAdvanceSearch = false, | ||||
|             IsSearch = !option.SearchText.IsNullOrWhiteSpace() | ||||
|         }; | ||||
|  | ||||
|         var items = datas.Skip((option.StartIndex)).Take(option.Count); | ||||
|         ret.TotalCount = datas.Count(); | ||||
|  | ||||
|         ret.Items = func(items).ToList(); | ||||
|         return ret; | ||||
|     } | ||||
| } | ||||
|   | ||||
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
| After Width: | Height: | Size: 177 KiB | 
| @@ -4,7 +4,7 @@ | ||||
| 	<Import Project="..\..\PackNuget.props" /> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>net47;netstandard2.0;net6.0;net6.0-windows;net8.0;$(OtherTargetFrameworks);net8.0-windows;</TargetFrameworks> | ||||
| 		<TargetFrameworks>net462;netstandard2.0;net6.0;net6.0-windows;net8.0;$(OtherTargetFrameworks);net8.0-windows;</TargetFrameworks> | ||||
| 		<AssemblyName>ThingsGateway.NewLife.X</AssemblyName> | ||||
| 		<RootNamespace>ThingsGateway.NewLife</RootNamespace> | ||||
| 		<AssemblyTitle>工具核心库</AssemblyTitle> | ||||
| @@ -12,9 +12,6 @@ | ||||
| 		<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
| 		<SignAssembly>True</SignAssembly> | ||||
| 		<AssemblyOriginatorKeyFile>newlife.snk</AssemblyOriginatorKeyFile> | ||||
| 		 | ||||
|  | ||||
|  | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| @@ -24,7 +21,7 @@ | ||||
| 		<None Remove="..\..\..\README.zh-CN.md" Pack="false" PackagePath="\" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<PropertyGroup Condition="'$(TargetFramework)'=='net47' or '$(TargetFramework)'=='net5.0-windows' or '$(TargetFramework)'=='net6.0-windows' or '$(TargetFramework)'=='net7.0-windows' or '$(TargetFramework)'=='net8.0-windows'"> | ||||
| 	<PropertyGroup Condition="'$(TargetFramework)'=='net462' or '$(TargetFramework)'=='net5.0-windows' or '$(TargetFramework)'=='net6.0-windows' or '$(TargetFramework)'=='net7.0-windows' or '$(TargetFramework)'=='net8.0-windows'"> | ||||
| 		<DefineConstants>__WIN__</DefineConstants> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| @@ -35,11 +32,12 @@ | ||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'"> | ||||
| 		<PackageReference Include="System.Memory" Version="4.6.3" /> | ||||
| 	</ItemGroup> | ||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='net47'"> | ||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='net462'"> | ||||
| 		<PackageReference Include="System.Memory" Version="4.6.3" /> | ||||
| 		<PackageReference Include="System.ValueTuple" Version="4.6.1" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='net47'"> | ||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='net462'"> | ||||
| 		<Using Include="System.Net.Http" /> | ||||
| 		<Reference Include="Microsoft.VisualBasic" /> | ||||
| 		<Reference Include="System.Management" /> | ||||
| @@ -54,10 +52,10 @@ | ||||
| 		<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<PropertyGroup Condition="$(TargetFramework)=='net6.0'"> | ||||
| 	<PropertyGroup Condition="$(TargetFramework)=='net6.0' OR $(TargetFramework)=='net6.0-windows'"> | ||||
| 		<DefineConstants>$(DefineConstants);PLAT_THREADPOOLWORKITEM;PLAT_MRVTSC</DefineConstants> | ||||
| 	</PropertyGroup> | ||||
| 	<PropertyGroup Condition="$(TargetFramework)=='net8.0'"> | ||||
| 	<PropertyGroup Condition="$(TargetFramework)=='net8.0' OR $(TargetFramework)=='net8.0-windows'"> | ||||
| 		<DefineConstants>$(DefineConstants);PLAT_THREADPOOLWORKITEM;PLAT_MRVTSC</DefineConstants> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| @@ -66,7 +64,7 @@ | ||||
| 		<IncludeAsyncInterfaces>true</IncludeAsyncInterfaces> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<PropertyGroup Condition="$(TargetFramework)=='net47'"> | ||||
| 	<PropertyGroup Condition="$(TargetFramework)=='net462'"> | ||||
| 		<DefineConstants>$(DefineConstants);PLAT_MRVTSC</DefineConstants> | ||||
| 		<IncludeAsyncInterfaces>true</IncludeAsyncInterfaces> | ||||
| 	</PropertyGroup> | ||||
| @@ -88,6 +86,6 @@ | ||||
| 		<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> | ||||
| 	</ItemGroup>--> | ||||
|  | ||||
| 	 | ||||
|  | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -7,7 +7,6 @@ | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<FrameworkReference Include="Microsoft.AspNetCore.App" /> | ||||
| 		<PackageReference Include="Photino.NET" Version="4.0.16" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
|   | ||||
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 177 KiB | 
| @@ -24,7 +24,7 @@ | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="SqlSugarCore.Dm" Version="8.8.2" /> | ||||
| 		<PackageReference Include="SqlSugarCore.Kdbndp" Version="9.3.7.905" /> | ||||
| 		<PackageReference Include="SqlSugarCore.Kdbndp" Version="9.3.7.1030" /> | ||||
| 		<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.20" /> | ||||
| 		<!--<PackageReference Include="Microsoft.Data.Sqlite" Version="$(NET10Version)" />--> | ||||
| 		<PackageReference Include="MySqlConnector" Version="2.4.0" /> | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| <Project> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<PluginVersion>10.12.17</PluginVersion> | ||||
| 		<ProPluginVersion>10.12.17</ProPluginVersion> | ||||
| 		<DefaultVersion>10.12.17</DefaultVersion> | ||||
| 		<PluginVersion>10.12.24</PluginVersion> | ||||
| 		<ProPluginVersion>10.12.24</ProPluginVersion> | ||||
| 		<DefaultVersion>10.12.24</DefaultVersion> | ||||
| 		<AuthenticationVersion>10.11.7</AuthenticationVersion> | ||||
| 		<SourceGeneratorVersion>10.11.7</SourceGeneratorVersion> | ||||
| 		<NET8Version>8.0.21</NET8Version> | ||||
| @@ -22,7 +22,9 @@ | ||||
| 		<OtherTargetFrameworks>net10.0</OtherTargetFrameworks> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<RestoreEnablePackagePruning Condition="'$(TargetFramework)' == 'net462' "> false</RestoreEnablePackagePruning> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<PropertyGroup Condition=" '$(TargetFramework)' != 'net8.0' "> | ||||
| 		<PluginTargetFramework>net10.0</PluginTargetFramework> | ||||
|   | ||||
| @@ -333,6 +333,10 @@ public abstract class DeviceBase : AsyncAndSyncDisposableObject, IDevice | ||||
|     /// <inheritdoc/> | ||||
|     private Task SendAsync(ISendMessage sendMessage, IClientChannel channel, CancellationToken token = default) | ||||
|     { | ||||
|         if(!channel.Online) | ||||
|         { | ||||
|             throw new InvalidOperationException("Channel is offline"); | ||||
|         } | ||||
|         return SendAsync(this, sendMessage, channel, token); | ||||
|  | ||||
|         static async PooledTask SendAsync(DeviceBase @this, ISendMessage sendMessage, IClientChannel channel, CancellationToken token) | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
| 			<CopyToOutputDirectory>Never</CopyToOutputDirectory> | ||||
| 		</EmbeddedResource> | ||||
| 	</ItemGroup> | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\..\Admin\ThingsGateway.NewLife.X\ThingsGateway.NewLife.X.csproj" /> | ||||
|   | ||||
| @@ -509,34 +509,16 @@ internal sealed class AlarmTask : IDisposable | ||||
|             { | ||||
|                 scheduledTask.Change(100, 100); | ||||
|             } | ||||
|  | ||||
|             ParallelOptions.CancellationToken = cancellation; | ||||
|             // 遍历设备变量列表 | ||||
|             if (!GlobalData.AlarmEnableIdVariables.IsEmpty) | ||||
|             { | ||||
|                 // 使用 Parallel.ForEach 执行指定的操作 | ||||
|                 Parallel.ForEach(GlobalData.AlarmEnableIdVariables, ParallelOptions, (item, state, index) => | ||||
|             { | ||||
|                 // 如果取消请求已经被触发,则结束任务 | ||||
|                 if (cancellation.IsCancellationRequested) | ||||
|                     return; | ||||
|  | ||||
|                 // 如果该变量的报警功能未启用,则跳过该变量 | ||||
|                 if (!item.Value.AlarmEnable) | ||||
|                     return; | ||||
|  | ||||
|                 // 如果该变量离线,则跳过该变量 | ||||
|                 if (!item.Value.IsOnline) | ||||
|                     return; | ||||
|  | ||||
|                 // 对该变量进行报警分析 | ||||
|                 AlarmAnalysis(item.Value); | ||||
|             }); | ||||
|                 Parallel.ForEach(GlobalData.AlarmEnableIdVariables, ParallelOptions, Analysis); | ||||
|             } | ||||
|  | ||||
|             else | ||||
|             { | ||||
|                 //if (scheduledTask.Period != 5000) | ||||
|                 //    scheduledTask.Change(0, 5000); // 如果没有启用报警的变量,则设置下次执行时间为5秒后 | ||||
|                 scheduledTask.SetNext(5000); // 如果没有启用报警的变量,则设置下次执行时间为5秒后 | ||||
|             } | ||||
|  | ||||
| @@ -552,6 +534,21 @@ internal sealed class AlarmTask : IDisposable | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void Analysis(KeyValuePair<long, VariableRuntime> item, ParallelLoopState state, long index) | ||||
|     { | ||||
|         // 如果取消请求已经被触发,则结束任务 | ||||
|         if (state.ShouldExitCurrentIteration) | ||||
|             return; | ||||
|  | ||||
|         // 如果该变量的报警功能未启用,则跳过该变量 | ||||
|         if (!item.Value.AlarmEnable) | ||||
|             return; | ||||
|  | ||||
|         // 如果该变量离线,则跳过该变量 | ||||
|         if (!item.Value.IsOnline) | ||||
|             return; | ||||
|  | ||||
|         // 对该变量进行报警分析 | ||||
|         AlarmAnalysis(item.Value); | ||||
|     } | ||||
| } | ||||
|   | ||||
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/Plugin/ThingsGateway.Debug.Photino/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 177 KiB | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 177 KiB | 
| @@ -10,6 +10,7 @@ | ||||
|  | ||||
| using Riok.Mapperly.Abstractions; | ||||
|  | ||||
| using ThingsGateway.Common; | ||||
| using ThingsGateway.DB; | ||||
|  | ||||
| namespace ThingsGateway.Plugin.DB; | ||||
|   | ||||
| @@ -171,10 +171,10 @@ public partial class MqttCollect : CollectBase | ||||
|                     mqttClientSubscribeOptionsBuilder = mqttClientSubscribeOptionsBuilder.WithTopicFilter( | ||||
|                         f => f.WithTopic(item)); | ||||
|                 } | ||||
|                 var mqttClientSubscribeOptions = mqttClientSubscribeOptionsBuilder.Build(); | ||||
|                 if (mqttClientSubscribeOptions.TopicFilters.Count > 0) | ||||
|                     _mqttSubscribeOptions = mqttClientSubscribeOptions; | ||||
|             } | ||||
|             var mqttClientSubscribeOptions = mqttClientSubscribeOptionsBuilder.Build(); | ||||
|             if (mqttClientSubscribeOptions.TopicFilters.Count > 0) | ||||
|                 _mqttSubscribeOptions = mqttClientSubscribeOptions; | ||||
|  | ||||
|             return Task.FromResult(dataResult); | ||||
|         } | ||||
|   | ||||
| @@ -20,6 +20,8 @@ using System.Diagnostics.CodeAnalysis; | ||||
| using ThingsGateway.Extension; | ||||
| using ThingsGateway.Foundation.OpcDa; | ||||
| using ThingsGateway.Foundation.OpcDa.Rcw; | ||||
| using ThingsGateway.Common; | ||||
|  | ||||
|  | ||||
| #if Plugin | ||||
|  | ||||
|   | ||||
| @@ -35,6 +35,8 @@ using ThingsGateway.Razor; | ||||
|  | ||||
| using TouchSocket.Core; | ||||
|  | ||||
| using ThingsGateway.Common; | ||||
|  | ||||
| namespace ThingsGateway.Debug; | ||||
|  | ||||
| /// <summary> | ||||
| @@ -73,7 +75,7 @@ public partial class OpcUaImportVariable | ||||
|             { | ||||
|                 Items = BuildTreeItemList(await PopulateBranchAsync(ObjectIds.ObjectsFolder), RenderTreeItem).ToList(); | ||||
|                 ShowSkeleton = false; | ||||
|                 await InvokeAsync(StateHasChanged); | ||||
|                 return InvokeAsync(StateHasChanged); | ||||
|             }); | ||||
|         } | ||||
|         await base.OnAfterRenderAsync(firstRender); | ||||
|   | ||||
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/ThingsGateway.Photino/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 177 KiB | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/ThingsGateway.RemoteWebApp/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 177 KiB | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/ThingsGateway.ScriptDebug/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 177 KiB | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/ThingsGateway.Server/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 177 KiB | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 257 KiB | 
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 177 KiB |