2025-05-28 16:45:30 +08:00
|
|
|
|
using IdentityModel.Client;
|
|
|
|
|
|
using JiShe.CollectBus.Common.Enums;
|
2025-04-25 13:42:08 +08:00
|
|
|
|
using JiShe.CollectBus.DynamicModule;
|
|
|
|
|
|
using JiShe.CollectBus.Interceptors;
|
2025-04-15 17:57:47 +08:00
|
|
|
|
using JiShe.CollectBus.IotSystems.MessageIssueds;
|
2025-04-25 13:42:08 +08:00
|
|
|
|
using JiShe.CollectBus.IotSystems.Protocols;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
using JiShe.CollectBus.Protocol;
|
2025-04-25 13:42:08 +08:00
|
|
|
|
using JiShe.CollectBus.Protocol.Interfaces;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
using JiShe.CollectBus.Protocol3761;
|
2025-04-25 13:42:08 +08:00
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
2025-04-25 13:42:08 +08:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2025-04-16 16:12:38 +08:00
|
|
|
|
using System.Diagnostics;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
using System.IO;
|
2025-04-16 16:12:38 +08:00
|
|
|
|
using System.Linq;
|
2025-04-24 21:01:01 +08:00
|
|
|
|
using System.Reflection;
|
2025-04-25 13:42:08 +08:00
|
|
|
|
using System.Threading.Tasks;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
using TouchSocket.Sockets;
|
|
|
|
|
|
using Volo.Abp;
|
2025-04-24 00:34:00 +08:00
|
|
|
|
using Volo.Abp.Modularity;
|
2025-04-15 17:57:47 +08:00
|
|
|
|
|
|
|
|
|
|
namespace JiShe.CollectBus.Samples;
|
|
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
2025-04-16 16:12:38 +08:00
|
|
|
|
public class TestAppService : CollectBusAppService
|
2025-04-15 17:57:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
private readonly ILogger<TestAppService> _logger;
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//private readonly ICassandraRepository<MessageIssued, string> _messageReceivedCassandraRepository;
|
|
|
|
|
|
//private readonly ICassandraProvider _cassandraProvider;
|
2025-04-22 21:01:28 +08:00
|
|
|
|
private readonly IProtocolService _protocolService;
|
2025-04-24 00:34:00 +08:00
|
|
|
|
private readonly IServiceProvider _serviceProvider;
|
2025-04-24 21:01:01 +08:00
|
|
|
|
private readonly IDynamicModuleManager _dynamicModuleManager;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
private readonly IServiceCollection _serviceDescriptors;
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-04-15 17:57:47 +08:00
|
|
|
|
public TestAppService(
|
|
|
|
|
|
ILogger<TestAppService> logger,
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//ICassandraRepository<MessageIssued, string> messageReceivedCassandraRepository,
|
|
|
|
|
|
//ICassandraProvider cassandraProvider,
|
2025-05-28 16:45:30 +08:00
|
|
|
|
IProtocolService protocolService,IServiceProvider serviceProvider, IDynamicModuleManager dynamicModuleManager, IServiceCollection serviceDescriptors)
|
2025-04-15 17:57:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
_logger = logger;
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//_messageReceivedCassandraRepository = messageReceivedCassandraRepository;
|
|
|
|
|
|
//_cassandraProvider = cassandraProvider;
|
2025-04-22 21:01:28 +08:00
|
|
|
|
_protocolService = protocolService;
|
2025-04-24 00:34:00 +08:00
|
|
|
|
_serviceProvider = serviceProvider;
|
2025-04-24 21:01:01 +08:00
|
|
|
|
_dynamicModuleManager = dynamicModuleManager;
|
2025-05-28 16:45:30 +08:00
|
|
|
|
_serviceDescriptors = serviceDescriptors;
|
2025-04-15 17:57:47 +08:00
|
|
|
|
}
|
2025-04-16 16:12:38 +08:00
|
|
|
|
public async Task AddMessageOfCassandra()
|
2025-04-15 17:57:47 +08:00
|
|
|
|
{
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//var stopwatch = Stopwatch.StartNew();
|
|
|
|
|
|
//for (int i = 1; i <= 10000; i++)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var str = Guid.NewGuid().ToString();
|
|
|
|
|
|
// await _messageReceivedCassandraRepository.InsertAsync(new MessageIssued
|
|
|
|
|
|
// {
|
|
|
|
|
|
// ClientId = str,
|
|
|
|
|
|
// DeviceNo = i.ToString(),
|
|
|
|
|
|
// MessageId = str,
|
|
|
|
|
|
// Type = IssuedEventType.Data,
|
|
|
|
|
|
// Id = str,
|
|
|
|
|
|
// Message = str.GetBytes()
|
|
|
|
|
|
// });
|
|
|
|
|
|
//}
|
|
|
|
|
|
//stopwatch.Stop();
|
|
|
|
|
|
//_logger.LogWarning($"插入 {10000} 条记录完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
|
2025-04-16 16:12:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task AddMessageOfBulkInsertCassandra()
|
|
|
|
|
|
{
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//var records = new List<MessageIssued>();
|
|
|
|
|
|
//var prepared = await _cassandraProvider.Session.PrepareAsync(
|
|
|
|
|
|
// $"INSERT INTO {_cassandraProvider.CassandraConfig.Keyspace}.{nameof(MessageIssued)} (id, clientid, message, deviceno,type,messageid) VALUES (?, ?, ?, ?, ?, ?)");
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//for (int i = 1; i <= 100000; i++)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var str = Guid.NewGuid().ToString();
|
|
|
|
|
|
// records.Add(new MessageIssued
|
|
|
|
|
|
// {
|
|
|
|
|
|
// ClientId = str,
|
|
|
|
|
|
// DeviceNo = i.ToString(),
|
|
|
|
|
|
// MessageId = str,
|
|
|
|
|
|
// Type = IssuedEventType.Data,
|
|
|
|
|
|
// Id = str,
|
|
|
|
|
|
// Message = str.GetBytes()
|
|
|
|
|
|
// });
|
|
|
|
|
|
//}
|
|
|
|
|
|
//var stopwatch = Stopwatch.StartNew();
|
|
|
|
|
|
//await BulkInsertAsync(_cassandraProvider.Session, prepared, records);
|
|
|
|
|
|
//stopwatch.Stop();
|
|
|
|
|
|
//_logger.LogWarning($"插入 {100000} 条记录完成,耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
|
2025-04-16 16:12:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
//private static async Task BulkInsertAsync(ISession session, PreparedStatement prepared, List<MessageIssued> records)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var tasks = new List<Task>();
|
|
|
|
|
|
// var batch = new BatchStatement();
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
// for (int i = 0; i < records.Count; i++)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var record = records[i];
|
|
|
|
|
|
// var boundStatement = prepared.Bind(
|
|
|
|
|
|
// record.Id,
|
|
|
|
|
|
// record.ClientId,
|
|
|
|
|
|
// record.Message,
|
|
|
|
|
|
// record.DeviceNo,
|
|
|
|
|
|
// (int)record.Type,
|
|
|
|
|
|
// record.MessageId);
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
// // 设置一致性级别为ONE以提高性能
|
|
|
|
|
|
// boundStatement.SetConsistencyLevel(ConsistencyLevel.One);
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
// batch.Add(boundStatement);
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
// // 当达到批处理大小时执行
|
|
|
|
|
|
// if (batch.Statements.Count() >= 1000 || i == records.Count - 1)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// tasks.Add(session.ExecuteAsync(batch));
|
|
|
|
|
|
// batch = new BatchStatement();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
2025-04-16 16:12:38 +08:00
|
|
|
|
|
2025-05-26 11:20:32 +08:00
|
|
|
|
// // 等待所有批处理完成
|
|
|
|
|
|
// await Task.WhenAll(tasks);
|
|
|
|
|
|
//}
|
2025-04-21 09:54:34 +08:00
|
|
|
|
|
|
|
|
|
|
[LogIntercept]
|
2025-04-22 21:01:28 +08:00
|
|
|
|
public virtual Task<string> LogInterceptorTest(string str)
|
2025-04-21 09:54:34 +08:00
|
|
|
|
{
|
|
|
|
|
|
_logger.LogWarning(str);
|
2025-04-22 21:01:28 +08:00
|
|
|
|
return Task.FromResult(str) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual async Task<ProtocolInfo> GetProtocol(string deviceCode, bool isSpecial = false)
|
|
|
|
|
|
{
|
|
|
|
|
|
var protocol = await _protocolService.FirstOrDefaultByDeviceAsync(deviceCode, isSpecial);
|
|
|
|
|
|
return protocol;
|
2025-04-21 09:54:34 +08:00
|
|
|
|
}
|
2025-04-24 00:34:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 重新加载插件方法
|
|
|
|
|
|
public async Task ReloadPluginsAsync()
|
|
|
|
|
|
{
|
2025-04-24 21:01:01 +08:00
|
|
|
|
var aa = Assembly.LoadFile(
|
2025-05-28 16:45:30 +08:00
|
|
|
|
@"E:\Devlopment\JiShe.CollectBusDev01\web\JiShe.CollectBus.Host\bin\Debug\net8.0\Plugins\JiShe.CollectBus.Protocol.Test.dll");
|
2025-04-24 21:01:01 +08:00
|
|
|
|
var module = aa.GetTypes().First(a=> typeof(IAbpModule).IsAssignableFrom(a));
|
2025-05-28 16:45:30 +08:00
|
|
|
|
await _dynamicModuleManager.LoadModuleAsync(module);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<bool> TestPlugins()
|
|
|
|
|
|
{
|
|
|
|
|
|
var executor = _serviceProvider.GetRequiredService<AnalysisStrategyContext>();
|
|
|
|
|
|
return await executor.ExecuteAsync<string>("TestServer", "TestServer");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 注册策略
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RegisterProtocolAnalysis()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 扫描并注册所有策略
|
|
|
|
|
|
var strategyMetadata = new Dictionary<(string, Type), Type>();
|
|
|
|
|
|
_serviceDescriptors.AddTransient<AnalysisStrategyContext>();
|
|
|
|
|
|
|
|
|
|
|
|
// 批量注册
|
|
|
|
|
|
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(assemblyPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var dllFiles = Directory.GetFiles(Path.Combine(assemblyPath, "Plugins"), "*.dll");
|
|
|
|
|
|
foreach (var file in dllFiles)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 跳过已加载的程序集
|
|
|
|
|
|
var assemblyName = AssemblyName.GetAssemblyName(file);
|
|
|
|
|
|
var existingAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
|
|
|
|
|
.FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName);
|
|
|
|
|
|
var assembly = existingAssembly ?? Assembly.LoadFrom(file);
|
|
|
|
|
|
// 实现IAnalysisStrategy接口
|
|
|
|
|
|
var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<>)));
|
|
|
|
|
|
if (!analysisStrategyTypes.Any())
|
|
|
|
|
|
continue;
|
|
|
|
|
|
foreach (var analysisStrategyType in analysisStrategyTypes)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 通过反射获取静态元数据
|
|
|
|
|
|
var strategyType = analysisStrategyType.Name;
|
|
|
|
|
|
var genericArgs = analysisStrategyType.GetInterface($"IAnalysisStrategy`1")!.GetGenericArguments();
|
|
|
|
|
|
var inputType = genericArgs[0];
|
|
|
|
|
|
// 注册策略实现
|
|
|
|
|
|
_serviceDescriptors.AddTransient(analysisStrategyType);
|
|
|
|
|
|
strategyMetadata[(strategyType, inputType)] = analysisStrategyType;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 注册元数据字典
|
|
|
|
|
|
_serviceDescriptors.AddSingleton(strategyMetadata);
|
|
|
|
|
|
|
|
|
|
|
|
// 注册策略解析工厂
|
|
|
|
|
|
_serviceDescriptors.AddTransient<Func<string, Type, object?>>(provider => (name, inputType) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var metadata = provider.GetRequiredService<Dictionary<(string, Type), Type>>();
|
|
|
|
|
|
if (metadata.TryGetValue((name, inputType), out var strategyType))
|
|
|
|
|
|
{
|
|
|
|
|
|
return provider.GetRequiredService(strategyType);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var logger = provider.GetRequiredService<ILogger<AnalysisStrategyContext>>();
|
|
|
|
|
|
logger.LogWarning($"未能找到解析策略:{name}-{inputType}");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-04-24 00:34:00 +08:00
|
|
|
|
}
|
2025-04-15 17:57:47 +08:00
|
|
|
|
}
|