|
@ -8,6 +8,7 @@ using CellularManagement.Domain.Services; |
|
|
using X1.DynamicClientCore.Features; |
|
|
using X1.DynamicClientCore.Features; |
|
|
using CellularManagement.Domain.Repositories.NetworkProfile; |
|
|
using CellularManagement.Domain.Repositories.NetworkProfile; |
|
|
using X1.DynamicClientCore.Models; |
|
|
using X1.DynamicClientCore.Models; |
|
|
|
|
|
using X1.Domain.Models; |
|
|
|
|
|
|
|
|
namespace CellularManagement.Application.Features.DeviceRuntimes.Commands.StartDeviceRuntime; |
|
|
namespace CellularManagement.Application.Features.DeviceRuntimes.Commands.StartDeviceRuntime; |
|
|
|
|
|
|
|
@ -23,6 +24,7 @@ public class StartDeviceRuntimeCommandHandler : IRequestHandler<StartDeviceRunti |
|
|
private readonly ICurrentUserService _currentUserService; |
|
|
private readonly ICurrentUserService _currentUserService; |
|
|
private readonly IInstrumentProtocolClient _protocolClient; |
|
|
private readonly IInstrumentProtocolClient _protocolClient; |
|
|
private readonly INetworkStackConfigRepository _networkStackConfigRepository; |
|
|
private readonly INetworkStackConfigRepository _networkStackConfigRepository; |
|
|
|
|
|
private readonly ICellularDeviceRuntimeDetailRepository _detailRepository; |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// 初始化命令处理器
|
|
|
/// 初始化命令处理器
|
|
@ -34,15 +36,17 @@ public class StartDeviceRuntimeCommandHandler : IRequestHandler<StartDeviceRunti |
|
|
ILogger<StartDeviceRuntimeCommandHandler> logger, |
|
|
ILogger<StartDeviceRuntimeCommandHandler> logger, |
|
|
IUnitOfWork unitOfWork, |
|
|
IUnitOfWork unitOfWork, |
|
|
ICurrentUserService currentUserService, |
|
|
ICurrentUserService currentUserService, |
|
|
IInstrumentProtocolClient protocolClient) |
|
|
IInstrumentProtocolClient protocolClient, |
|
|
|
|
|
ICellularDeviceRuntimeDetailRepository detailRepository) |
|
|
{ |
|
|
{ |
|
|
_deviceRuntimeRepository = deviceRuntimeRepository; |
|
|
_deviceRuntimeRepository = deviceRuntimeRepository; |
|
|
_deviceRepository = deviceRepository; |
|
|
_deviceRepository = deviceRepository; |
|
|
_logger = logger; |
|
|
_logger = logger; |
|
|
_unitOfWork = unitOfWork; |
|
|
_unitOfWork = unitOfWork; |
|
|
_currentUserService = currentUserService; |
|
|
_currentUserService = currentUserService; |
|
|
_protocolClient= protocolClient; |
|
|
_protocolClient = protocolClient; |
|
|
_networkStackConfigRepository = networkStackConfigRepository; |
|
|
_networkStackConfigRepository = networkStackConfigRepository; |
|
|
|
|
|
_detailRepository = detailRepository; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
@ -52,7 +56,7 @@ public class StartDeviceRuntimeCommandHandler : IRequestHandler<StartDeviceRunti |
|
|
{ |
|
|
{ |
|
|
try |
|
|
try |
|
|
{ |
|
|
{ |
|
|
_logger.LogInformation("开始批量启动设备运行时状态,设备数量: {DeviceCount}", request.DeviceRequests.Count); |
|
|
_logger.LogInformation("开始批量启动设备运行时状态,设备数量: {DeviceCount}", request?.DeviceRequests?.Count ?? 0); |
|
|
|
|
|
|
|
|
// 验证命令参数
|
|
|
// 验证命令参数
|
|
|
if (!request.IsValid()) |
|
|
if (!request.IsValid()) |
|
@ -69,116 +73,134 @@ public class StartDeviceRuntimeCommandHandler : IRequestHandler<StartDeviceRunti |
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateFailure("用户未登录"); |
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateFailure("用户未登录"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var res = await _networkStackConfigRepository.GetNetworkStackConfigsByCodesAsync(request.DeviceRequests.Select(s => s.NetworkStackCode).ToArray(), cancellationToken); |
|
|
_logger.LogDebug("开始获取网络堆栈配置,网络堆栈代码: {NetworkStackCodes}", |
|
|
|
|
|
string.Join(", ", request.DeviceRequests.Select(r => r.NetworkStackCode))); |
|
|
|
|
|
|
|
|
//List<CellularNetworkConfiguration> Requests = new List<CellularNetworkConfiguration>();
|
|
|
// 获取网络堆栈配置
|
|
|
//foreach (var item in res)
|
|
|
var networkConfigs = await _networkStackConfigRepository.GetNetworkStackConfigsByCodesAsync( |
|
|
//{
|
|
|
request.DeviceRequests.Select(s => s.NetworkStackCode).ToArray(), cancellationToken); |
|
|
// Requests.Add(new CellularNetworkConfiguration
|
|
|
|
|
|
// {
|
|
|
if (networkConfigs == null || !networkConfigs.Any()) |
|
|
// DeviceCode= item.NetworkStackCode,
|
|
|
{ |
|
|
// RadioAccessNetworkConfiguration =item.RanName
|
|
|
_logger.LogWarning("未找到指定的网络堆栈配置"); |
|
|
// });
|
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateFailure("未找到指定的网络堆栈配置"); |
|
|
//}
|
|
|
} |
|
|
|
|
|
|
|
|
//var deviceResults = new List<DeviceStartResult>();
|
|
|
_logger.LogDebug("成功获取网络堆栈配置,配置数量: {ConfigCount}", networkConfigs.Count()); |
|
|
//var successCount = 0;
|
|
|
|
|
|
//var failureCount = 0;
|
|
|
// 生成运行时编码
|
|
|
|
|
|
var runtimeCode = await GenerateRuntimeCodeAsync(cancellationToken); |
|
|
//// 批量处理设备启动
|
|
|
if (string.IsNullOrEmpty(runtimeCode)) |
|
|
//foreach (var deviceRequest in request.DeviceRequests)
|
|
|
{ |
|
|
//{
|
|
|
_logger.LogError("生成运行时编码失败"); |
|
|
// try
|
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateFailure("生成运行时编码失败"); |
|
|
// {
|
|
|
} |
|
|
// _logger.LogInformation("开始启动设备,设备编号: {DeviceCode}, 网络栈配置编号: {NetworkStackCode}",
|
|
|
_logger.LogInformation("生成运行时编码: {RuntimeCode}", runtimeCode); |
|
|
// deviceRequest.DeviceCode, deviceRequest.NetworkStackCode);
|
|
|
|
|
|
|
|
|
// 构建网络配置请求
|
|
|
// // 获取设备运行时状态
|
|
|
var networkRequests = BuildNetworkConfigurationRequests(request, networkConfigs, runtimeCode); |
|
|
// var deviceRuntime = await _deviceRuntimeRepository.GetRuntimeByDeviceCodeAsync(deviceRequest.DeviceCode, cancellationToken);
|
|
|
|
|
|
// if (deviceRuntime == null)
|
|
|
_logger.LogInformation("成功构建网络配置请求,请求数量: {RequestCount}", networkRequests?.Count ?? 0); |
|
|
// {
|
|
|
|
|
|
// _logger.LogWarning("设备运行时状态不存在,设备编号: {DeviceCode}", deviceRequest.DeviceCode);
|
|
|
// 检查是否有有效的网络配置请求
|
|
|
// deviceResults.Add(new DeviceStartResult
|
|
|
if (networkRequests == null || !networkRequests.Any()) |
|
|
// {
|
|
|
{ |
|
|
// DeviceCode = deviceRequest.DeviceCode,
|
|
|
_logger.LogWarning("没有有效的网络配置请求,无法启动设备运行时"); |
|
|
// IsSuccess = false,
|
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateFailure("没有有效的网络配置请求,无法启动设备运行时"); |
|
|
// ErrorMessage = $"设备编号 {deviceRequest.DeviceCode} 的运行时状态不存在"
|
|
|
} |
|
|
// });
|
|
|
|
|
|
// failureCount++;
|
|
|
// 并行启动网络并收集结果
|
|
|
// continue;
|
|
|
var networkResults = new List<(bool Success, string DeviceCode, string ErrorMessage)>(); |
|
|
// }
|
|
|
_logger.LogInformation("开始并行启动网络,请求数量: {RequestCount}", networkRequests.Count); |
|
|
|
|
|
|
|
|
// // 检查设备是否已经在运行
|
|
|
await Parallel.ForEachAsync(networkRequests, async (networkRequest, cts) => |
|
|
// if (deviceRuntime.RuntimeStatus == DeviceRuntimeStatus.Running)
|
|
|
{ |
|
|
// {
|
|
|
try |
|
|
// _logger.LogWarning("设备已经在运行中,设备编号: {DeviceCode}", deviceRequest.DeviceCode);
|
|
|
{ |
|
|
// deviceResults.Add(new DeviceStartResult
|
|
|
_logger.LogDebug("启动网络,设备代码: {DeviceCode}, 运行时代码: {RuntimeCode}", |
|
|
// {
|
|
|
networkRequest.DeviceCode, networkRequest.RuntimeCode); |
|
|
// DeviceCode = deviceRequest.DeviceCode,
|
|
|
await _protocolClient.StartNetworkAsync(networkRequest); |
|
|
// IsSuccess = false,
|
|
|
_logger.LogDebug("网络启动成功,设备代码: {DeviceCode}", networkRequest.DeviceCode); |
|
|
// ErrorMessage = $"设备编号 {deviceRequest.DeviceCode} 已经在运行中"
|
|
|
networkResults.Add((true, networkRequest.DeviceCode, string.Empty)); |
|
|
// });
|
|
|
} |
|
|
// failureCount++;
|
|
|
catch (Exception ex) |
|
|
// continue;
|
|
|
{ |
|
|
// }
|
|
|
var errorMessage = $"网络启动失败: {ex.Message}"; |
|
|
|
|
|
_logger.LogError(ex, "网络启动失败,设备代码: {DeviceCode}", networkRequest.DeviceCode); |
|
|
// // 生成运行编码
|
|
|
networkResults.Add((false, networkRequest.DeviceCode, errorMessage)); |
|
|
// var runtimeCode = await GenerateRuntimeCodeAsync(deviceRequest.DeviceCode, cancellationToken);
|
|
|
} |
|
|
|
|
|
}); |
|
|
// // 启动设备
|
|
|
|
|
|
// deviceRuntime.Start(deviceRequest.NetworkStackCode, runtimeCode);
|
|
|
// 检查网络启动结果
|
|
|
|
|
|
var successfulDevices = networkResults.Where(r => r.Success).Select(r => r.DeviceCode).ToHashSet(); |
|
|
// // 更新到数据库
|
|
|
var failedDevices = networkResults.Where(r => !r.Success).ToList(); |
|
|
// _deviceRuntimeRepository.UpdateRuntime(deviceRuntime);
|
|
|
|
|
|
|
|
|
if (failedDevices.Any()) |
|
|
// _logger.LogInformation("设备启动成功,设备编号: {DeviceCode}, 运行编码: {RuntimeCode}",
|
|
|
{ |
|
|
// deviceRuntime.DeviceCode, deviceRuntime.RuntimeCode);
|
|
|
_logger.LogWarning("部分设备网络启动失败,失败设备: {FailedDevices}", |
|
|
|
|
|
string.Join(", ", failedDevices.Select(f => f.DeviceCode))); |
|
|
// // 添加到结果列表
|
|
|
} |
|
|
// deviceResults.Add(new DeviceStartResult
|
|
|
|
|
|
// {
|
|
|
// 只为成功启动网络的设备创建运行时详情和更新状态
|
|
|
// DeviceCode = deviceRuntime.DeviceCode,
|
|
|
var runtimeDetails = new List<CellularDeviceRuntimeDetail>(); |
|
|
// Id = deviceRuntime.Id,
|
|
|
var updatedRuntimes = new List<CellularDeviceRuntime>(); |
|
|
// RuntimeStatus = deviceRuntime.RuntimeStatus.ToString(),
|
|
|
|
|
|
// NetworkStackCode = deviceRuntime.NetworkStackCode,
|
|
|
foreach (var deviceRequest in request.DeviceRequests) |
|
|
// UpdatedAt = deviceRuntime.UpdatedAt ?? DateTime.UtcNow,
|
|
|
{ |
|
|
// IsSuccess = true
|
|
|
// 只处理网络启动成功的设备
|
|
|
// });
|
|
|
if (!successfulDevices.Contains(deviceRequest.DeviceCode)) |
|
|
// successCount++;
|
|
|
{ |
|
|
// }
|
|
|
_logger.LogWarning("跳过处理网络启动失败的设备,设备代码: {DeviceCode}", deviceRequest.DeviceCode); |
|
|
// catch (Exception ex)
|
|
|
continue; |
|
|
// {
|
|
|
} |
|
|
// _logger.LogError(ex, "启动设备失败,设备编号: {DeviceCode}", deviceRequest.DeviceCode);
|
|
|
|
|
|
// deviceResults.Add(new DeviceStartResult
|
|
|
_logger.LogDebug("处理设备运行时,设备代码: {DeviceCode}", deviceRequest.DeviceCode); |
|
|
// {
|
|
|
|
|
|
// DeviceCode = deviceRequest.DeviceCode,
|
|
|
// 创建运行时详情
|
|
|
// IsSuccess = false,
|
|
|
var detail = CellularDeviceRuntimeDetail.Create( |
|
|
// ErrorMessage = $"启动设备失败: {ex.Message}"
|
|
|
deviceRequest.DeviceCode, |
|
|
// });
|
|
|
runtimeCode, |
|
|
// failureCount++;
|
|
|
deviceRequest.NetworkStackCode, |
|
|
// }
|
|
|
currentUser); |
|
|
//}
|
|
|
runtimeDetails.Add(detail); |
|
|
|
|
|
|
|
|
//// 保存所有更改
|
|
|
// 获取并更新设备运行时状态
|
|
|
//await _unitOfWork.SaveChangesAsync(cancellationToken);
|
|
|
var deviceRuntime = await _deviceRuntimeRepository.GetRuntimeByDeviceCodeAsync(deviceRequest.DeviceCode, cancellationToken); |
|
|
|
|
|
if (deviceRuntime == null) |
|
|
//// 构建响应
|
|
|
{ |
|
|
//var response = new StartDeviceRuntimeResponse
|
|
|
_logger.LogWarning("设备运行时不存在,设备代码: {DeviceCode}", deviceRequest.DeviceCode); |
|
|
//{
|
|
|
continue; |
|
|
// DeviceResults = deviceResults,
|
|
|
} |
|
|
// Summary = new BatchOperationSummary
|
|
|
|
|
|
// {
|
|
|
deviceRuntime.Start(deviceRequest.NetworkStackCode, runtimeCode); |
|
|
// TotalCount = request.DeviceRequests.Count,
|
|
|
_deviceRuntimeRepository.UpdateRuntime(deviceRuntime); |
|
|
// SuccessCount = successCount,
|
|
|
updatedRuntimes.Add(deviceRuntime); |
|
|
// FailureCount = failureCount
|
|
|
|
|
|
// }
|
|
|
_logger.LogDebug("设备运行时状态已更新,设备代码: {DeviceCode}, 网络堆栈代码: {NetworkStackCode}", |
|
|
//};
|
|
|
deviceRequest.DeviceCode, deviceRequest.NetworkStackCode); |
|
|
|
|
|
} |
|
|
//_logger.LogInformation("批量启动设备完成,总数量: {TotalCount}, 成功: {SuccessCount}, 失败: {FailureCount}",
|
|
|
|
|
|
// response.Summary.TotalCount, response.Summary.SuccessCount, response.Summary.FailureCount);
|
|
|
// 批量保存运行时详情
|
|
|
|
|
|
if (runtimeDetails.Any()) |
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateSuccess(null); |
|
|
{ |
|
|
|
|
|
_logger.LogDebug("保存运行时详情,详情数量: {DetailCount}", runtimeDetails.Count); |
|
|
|
|
|
await _detailRepository.AddRangeAsync(runtimeDetails); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 保存所有更改
|
|
|
|
|
|
await _unitOfWork.SaveChangesAsync(cancellationToken); |
|
|
|
|
|
_logger.LogInformation("批量启动设备运行时状态完成,运行时代码: {RuntimeCode}, 成功设备数: {SuccessCount}, 失败设备数: {FailureCount}", |
|
|
|
|
|
runtimeCode, successfulDevices.Count, failedDevices.Count); |
|
|
|
|
|
|
|
|
|
|
|
return OperationResult<StartDeviceRuntimeResponse>.CreateSuccess(new StartDeviceRuntimeResponse |
|
|
|
|
|
{ |
|
|
|
|
|
Summary = new BatchOperationSummary |
|
|
|
|
|
{ |
|
|
|
|
|
TotalCount = request.DeviceRequests.Count, |
|
|
|
|
|
SuccessCount = successfulDevices.Count, |
|
|
|
|
|
FailureCount = failedDevices.Count |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
catch (Exception ex) |
|
|
catch (Exception ex) |
|
|
{ |
|
|
{ |
|
@ -188,28 +210,72 @@ public class StartDeviceRuntimeCommandHandler : IRequestHandler<StartDeviceRunti |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// 生成运行编码
|
|
|
/// 生成唯一的运行时编码
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
private async Task<string> GenerateRuntimeCodeAsync(string deviceCode, CancellationToken cancellationToken) |
|
|
/// <param name="cancellationToken">取消令牌</param>
|
|
|
|
|
|
/// <returns>生成的运行时编码</returns>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// 运行时编码格式:RT-{时间戳}-{序号}
|
|
|
|
|
|
/// - 时间戳:yyyyMMddHHmmssfff 格式,精确到毫秒
|
|
|
|
|
|
/// - 序号:基于当前运行时总数自动递增,至少3位数字
|
|
|
|
|
|
///
|
|
|
|
|
|
/// 使用信号量确保在多线程环境下生成唯一的编码:
|
|
|
|
|
|
/// 1. 防止并发访问导致的序号重复
|
|
|
|
|
|
/// 2. 确保时间戳和序号的组合唯一性
|
|
|
|
|
|
/// 3. 避免数据库查询和插入之间的竞态条件
|
|
|
|
|
|
/// 4. 支持异步操作,避免死锁风险
|
|
|
|
|
|
/// 5. 控制并发访问数量,提高性能
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
private static readonly SemaphoreSlim _runtimeCodeSemaphore = new SemaphoreSlim(1, 1); |
|
|
|
|
|
private async Task<string> GenerateRuntimeCodeAsync(CancellationToken cancellationToken) |
|
|
{ |
|
|
{ |
|
|
// 获取当前设备运行时总数
|
|
|
// 使用信号量确保在多线程环境下生成唯一的运行时编码
|
|
|
|
|
|
await _runtimeCodeSemaphore.WaitAsync(cancellationToken); |
|
|
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
|
{ |
|
|
|
|
|
_logger.LogDebug("开始生成运行时编码,线程ID: {ThreadId}", Thread.CurrentThread.ManagedThreadId); |
|
|
|
|
|
|
|
|
|
|
|
// 获取当前设备运行时总数(异步调用)
|
|
|
var runtimeCount = await _deviceRuntimeRepository.GetRuntimeCountAsync(cancellationToken); |
|
|
var runtimeCount = await _deviceRuntimeRepository.GetRuntimeCountAsync(cancellationToken); |
|
|
|
|
|
_logger.LogDebug("当前运行时总数: {RuntimeCount}", runtimeCount); |
|
|
|
|
|
|
|
|
|
|
|
// 计算下一个序号
|
|
|
var nextNumber = runtimeCount + 1; |
|
|
var nextNumber = runtimeCount + 1; |
|
|
|
|
|
|
|
|
// 计算需要的位数,确保至少3位数
|
|
|
// 计算需要的位数,确保至少3位数
|
|
|
var digitCount = CalculateRequiredDigits(nextNumber); |
|
|
var digitCount = CalculateRequiredDigits(nextNumber); |
|
|
|
|
|
|
|
|
// 格式化序号,动态补0,确保从000开始
|
|
|
// 格式化序号为指定位数
|
|
|
var formattedNumber = nextNumber.ToString($"D{digitCount}"); |
|
|
var formattedNumber = nextNumber.ToString($"D{digitCount}"); |
|
|
|
|
|
|
|
|
// 生成运行编码格式:RT-000-DEVCODE, RT-001-DEVCODE 等
|
|
|
// 生成时间戳,精确到毫秒
|
|
|
var runtimeCode = $"RT-{formattedNumber}-{deviceCode}"; |
|
|
string timestamp = DateTime.Now.ToString("yyyyMMddHHmmssfff"); |
|
|
|
|
|
|
|
|
_logger.LogDebug("生成运行编码: {RuntimeCode}, 运行时总数: {RuntimeCount}, 位数: {DigitCount}", |
|
|
// 组装运行时编码
|
|
|
runtimeCode, runtimeCount, digitCount); |
|
|
var runtimeCode = $"RT-{timestamp}-{formattedNumber}"; |
|
|
|
|
|
|
|
|
|
|
|
_logger.LogDebug("成功生成运行时编码: {RuntimeCode}, 运行时总数: {RuntimeCount}, 序号: {NextNumber}, 位数: {DigitCount}, 线程ID: {ThreadId}", |
|
|
|
|
|
runtimeCode, runtimeCount, nextNumber, digitCount, Thread.CurrentThread.ManagedThreadId); |
|
|
|
|
|
|
|
|
return runtimeCode; |
|
|
return runtimeCode; |
|
|
} |
|
|
} |
|
|
|
|
|
catch (Exception ex) |
|
|
|
|
|
{ |
|
|
|
|
|
_logger.LogError(ex, "生成运行时编码失败,线程ID: {ThreadId}", Thread.CurrentThread.ManagedThreadId); |
|
|
|
|
|
// 重新抛出异常的原因:
|
|
|
|
|
|
// 1. 保持异常的原始堆栈跟踪信息,便于调试和问题定位
|
|
|
|
|
|
// 2. 确保上层调用者能够捕获到原始异常,进行适当的错误处理
|
|
|
|
|
|
// 3. 避免异常信息丢失,保持异常传播链的完整性
|
|
|
|
|
|
// 4. 符合异常处理的最佳实践:记录日志后重新抛出
|
|
|
|
|
|
throw; |
|
|
|
|
|
} |
|
|
|
|
|
finally |
|
|
|
|
|
{ |
|
|
|
|
|
// 确保信号量被释放
|
|
|
|
|
|
_runtimeCodeSemaphore.Release(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// 计算需要的位数
|
|
|
/// 计算需要的位数
|
|
@ -222,5 +288,101 @@ public class StartDeviceRuntimeCommandHandler : IRequestHandler<StartDeviceRunti |
|
|
// 1-999用3位,1000-9999用4位,10000-99999用5位,以此类推
|
|
|
// 1-999用3位,1000-9999用4位,10000-99999用5位,以此类推
|
|
|
var calculatedDigits = (int)Math.Floor(Math.Log10(number)) + 1; |
|
|
var calculatedDigits = (int)Math.Floor(Math.Log10(number)) + 1; |
|
|
return Math.Max(calculatedDigits, 3); // 确保至少3位数
|
|
|
return Math.Max(calculatedDigits, 3); // 确保至少3位数
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 构建网络配置请求
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="request">启动设备运行时命令</param>
|
|
|
|
|
|
/// <param name="networkConfigs">网络堆栈配置</param>
|
|
|
|
|
|
/// <param name="runtimeCode">运行时编码</param>
|
|
|
|
|
|
/// <returns>构建好的网络配置请求列表</returns>
|
|
|
|
|
|
private List<CellularNetworkConfiguration> BuildNetworkConfigurationRequests( |
|
|
|
|
|
StartDeviceRuntimeCommand request, |
|
|
|
|
|
IEnumerable<NetworkStackConfigBasicDto> networkConfigs, |
|
|
|
|
|
string runtimeCode) |
|
|
|
|
|
{ |
|
|
|
|
|
// 按NetworkStackCode分组网络配置,提高查询效率
|
|
|
|
|
|
var networkConfigsByCode = networkConfigs |
|
|
|
|
|
.Where(nc => !string.IsNullOrEmpty(nc.NetworkStackCode)) |
|
|
|
|
|
.GroupBy(nc => nc.NetworkStackCode!) |
|
|
|
|
|
.ToDictionary(g => g.Key, g => g.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
// 使用HashSet进行去重,提高性能
|
|
|
|
|
|
var processedDeviceNetworkPairs = new HashSet<string>(); |
|
|
|
|
|
|
|
|
|
|
|
return request.DeviceRequests |
|
|
|
|
|
.Where(deviceRequest => |
|
|
|
|
|
{ |
|
|
|
|
|
// 检查是否已处理过相同的设备-网络堆栈组合
|
|
|
|
|
|
var deviceNetworkKey = $"{deviceRequest.DeviceCode}_{deviceRequest.NetworkStackCode}"; |
|
|
|
|
|
if (processedDeviceNetworkPairs.Contains(deviceNetworkKey)) |
|
|
|
|
|
{ |
|
|
|
|
|
_logger.LogWarning("设备代码 {DeviceCode} 与网络堆栈 {NetworkStackCode} 的组合已存在,跳过重复处理", |
|
|
|
|
|
deviceRequest.DeviceCode, deviceRequest.NetworkStackCode); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否存在对应的网络配置
|
|
|
|
|
|
if (!networkConfigsByCode.TryGetValue(deviceRequest.NetworkStackCode, out var deviceNetworkConfigs)) |
|
|
|
|
|
{ |
|
|
|
|
|
_logger.LogWarning("未找到对应的网络配置,设备代码: {DeviceCode}, 网络堆栈代码: {NetworkStackCode}", |
|
|
|
|
|
deviceRequest.DeviceCode, deviceRequest.NetworkStackCode); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 验证配置有效性
|
|
|
|
|
|
var hasValidRanConfig = deviceNetworkConfigs.Any(s => !string.IsNullOrEmpty(s.RanConfigContent)); |
|
|
|
|
|
var hasValidNetworkConfigs = deviceNetworkConfigs.Any(s => |
|
|
|
|
|
!string.IsNullOrEmpty(s.IMSConfigContent) && !string.IsNullOrEmpty(s.CoreNetworkConfigContent)); |
|
|
|
|
|
|
|
|
|
|
|
if (!hasValidRanConfig && !hasValidNetworkConfigs) |
|
|
|
|
|
{ |
|
|
|
|
|
_logger.LogWarning("设备 {DeviceCode} 的网络配置既缺少RAN配置内容,又缺少有效的IMS和核心网配置内容,跳过处理", |
|
|
|
|
|
deviceRequest.DeviceCode); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
processedDeviceNetworkPairs.Add(deviceNetworkKey); |
|
|
|
|
|
return true; |
|
|
|
|
|
}) |
|
|
|
|
|
.Select(deviceRequest => |
|
|
|
|
|
{ |
|
|
|
|
|
var deviceNetworkConfigs = networkConfigsByCode[deviceRequest.NetworkStackCode]; |
|
|
|
|
|
|
|
|
|
|
|
// 构建CoreNetworkImsConfiguration列表
|
|
|
|
|
|
var coreNetworkImsConfigurations = deviceNetworkConfigs |
|
|
|
|
|
.Where(s => !string.IsNullOrEmpty(s.IMSConfigContent) && !string.IsNullOrEmpty(s.CoreNetworkConfigContent)) |
|
|
|
|
|
.Select(networkConfig => new CoreNetworkImsConfiguration |
|
|
|
|
|
{ |
|
|
|
|
|
Index = networkConfig.Index ?? 0, |
|
|
|
|
|
Plmn = "000000", |
|
|
|
|
|
CoreNetworkConfiguration = networkConfig.CoreNetworkConfigContent!, |
|
|
|
|
|
ImsServiceConfiguration = networkConfig.IMSConfigContent! |
|
|
|
|
|
}) |
|
|
|
|
|
.ToList(); |
|
|
|
|
|
|
|
|
|
|
|
// 获取RAN配置
|
|
|
|
|
|
var validRanConfig = deviceNetworkConfigs |
|
|
|
|
|
.Where(s => !string.IsNullOrEmpty(s.RanConfigContent)) |
|
|
|
|
|
.Select(s => s.RanConfigContent) |
|
|
|
|
|
.Distinct() |
|
|
|
|
|
.FirstOrDefault() ?? string.Empty; |
|
|
|
|
|
|
|
|
|
|
|
// 创建网络配置
|
|
|
|
|
|
var configuration = new CellularNetworkConfiguration |
|
|
|
|
|
{ |
|
|
|
|
|
RuntimeCode = runtimeCode, |
|
|
|
|
|
DeviceCode = deviceRequest.DeviceCode, |
|
|
|
|
|
RadioAccessNetworkConfiguration = validRanConfig, |
|
|
|
|
|
CoreNetworkImsConfigurations = coreNetworkImsConfigurations |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
_logger.LogDebug("构建网络配置请求,设备代码: {DeviceCode}, 网络堆栈代码: {NetworkStackCode}, 绑定关系数量: {BindingCount}", |
|
|
|
|
|
deviceRequest.DeviceCode, deviceRequest.NetworkStackCode, coreNetworkImsConfigurations.Count); |
|
|
|
|
|
|
|
|
|
|
|
return configuration; |
|
|
|
|
|
}) |
|
|
|
|
|
.ToList(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |