Browse Source
- 新增DeviceInfo模型,包含IsSuccess字段用于状态判断 - 实现IDeviceService接口和DeviceService实现类 - 支持Windows和Linux系统序列号获取 - 修复ParseSerialNumber方法,支持Linux输出格式解析 - 创建GetSerialNumberCommand和GetSerialNumberCommandHandler - 添加SystemController API控制器 - 修复CS0234编译错误,添加System.Net引用 - 更新依赖注入配置 - 完善错误处理和日志记录feature/protocol-log-Perfect
16 changed files with 597 additions and 14 deletions
@ -0,0 +1,34 @@ |
|||
using CoreAgent.Application.Commands.System; |
|||
using CoreAgent.Domain.Models.System; |
|||
using MediatR; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace CoreAgent.API.Controllers; |
|||
|
|||
/// <summary>
|
|||
/// 系统控制器
|
|||
/// </summary>
|
|||
public class SystemController : BaseApiController |
|||
{ |
|||
public SystemController(IMediator mediator, ILogger<SystemController> logger) |
|||
: base(mediator, logger) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取设备序列号(SN)
|
|||
/// </summary>
|
|||
/// <returns>设备信息</returns>
|
|||
[HttpGet("serial-number")] |
|||
public async Task<IActionResult> GetSerialNumber() |
|||
{ |
|||
_logger.LogInformation("收到获取设备序列号请求"); |
|||
|
|||
var command = new GetSerialNumberCommand(); |
|||
var result = await _mediator.Send(command); |
|||
|
|||
_logger.LogInformation("成功返回设备序列号: {SerialNumber}", result.Data?.SerialNumber); |
|||
|
|||
return result; |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
using CoreAgent.Domain.Models.Common; |
|||
using CoreAgent.Domain.Models.System; |
|||
using MediatR; |
|||
|
|||
namespace CoreAgent.Application.Commands.System; |
|||
|
|||
/// <summary>
|
|||
/// 获取设备序列号命令
|
|||
/// </summary>
|
|||
public class GetSerialNumberCommand : IRequest<ApiActionResult<DeviceInfo>> |
|||
{ |
|||
// 命令不需要额外参数,直接获取当前设备的序列号
|
|||
} |
@ -0,0 +1,51 @@ |
|||
using CoreAgent.Application.Commands.System; |
|||
using CoreAgent.Domain.Interfaces.System; |
|||
using CoreAgent.Domain.Models.Common; |
|||
using CoreAgent.Domain.Models.System; |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CoreAgent.Application.Handlers.System; |
|||
|
|||
/// <summary>
|
|||
/// 获取设备序列号命令处理器
|
|||
/// </summary>
|
|||
public class GetSerialNumberCommandHandler : IRequestHandler<GetSerialNumberCommand, ApiActionResult<DeviceInfo>> |
|||
{ |
|||
private readonly IDeviceService _deviceService; |
|||
private readonly ILogger<GetSerialNumberCommandHandler> _logger; |
|||
|
|||
public GetSerialNumberCommandHandler( |
|||
IDeviceService deviceService, |
|||
ILogger<GetSerialNumberCommandHandler> logger) |
|||
{ |
|||
_deviceService = deviceService ?? throw new ArgumentNullException(nameof(deviceService)); |
|||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); |
|||
} |
|||
|
|||
public async Task<ApiActionResult<DeviceInfo>> Handle(GetSerialNumberCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始处理获取设备序列号命令"); |
|||
|
|||
var deviceInfo = await _deviceService.GetSerialNumberAsync(); |
|||
|
|||
if (deviceInfo.IsSuccess) |
|||
{ |
|||
_logger.LogInformation("成功获取设备序列号: {SerialNumber}", deviceInfo.SerialNumber); |
|||
return ApiActionResult<DeviceInfo>.Ok(deviceInfo, "获取设备序列号成功"); |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("获取设备序列号失败,返回的序列号: {SerialNumber}", deviceInfo.SerialNumber); |
|||
return ApiActionResult<DeviceInfo>.Error("获取设备序列号失败", "DEVICE_SN_NOT_FOUND"); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "处理获取设备序列号命令时发生异常"); |
|||
return ApiActionResult<DeviceInfo>.Error("获取设备序列号失败", "DEVICE_SN_ERROR"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
using CoreAgent.Domain.Models.System; |
|||
|
|||
namespace CoreAgent.Domain.Interfaces.System; |
|||
|
|||
/// <summary>
|
|||
/// 设备服务接口
|
|||
/// </summary>
|
|||
public interface IDeviceService |
|||
{ |
|||
/// <summary>
|
|||
/// 获取设备序列号(SN)
|
|||
/// </summary>
|
|||
/// <returns>设备信息</returns>
|
|||
Task<DeviceInfo> GetSerialNumberAsync(); |
|||
|
|||
/// <summary>
|
|||
/// 获取设备序列号(SN)- 同步版本
|
|||
/// </summary>
|
|||
/// <returns>设备信息</returns>
|
|||
DeviceInfo GetSerialNumber(); |
|||
} |
@ -0,0 +1,22 @@ |
|||
namespace CoreAgent.Domain.Models.System; |
|||
|
|||
/// <summary>
|
|||
/// 设备信息模型
|
|||
/// </summary>
|
|||
public class DeviceInfo |
|||
{ |
|||
/// <summary>
|
|||
/// 是否成功获取到序列号
|
|||
/// </summary>
|
|||
public bool IsSuccess { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 设备序列号(SN)
|
|||
/// </summary>
|
|||
public string SerialNumber { get; set; } = string.Empty; |
|||
|
|||
/// <summary>
|
|||
/// 获取时间
|
|||
/// </summary>
|
|||
public DateTime Timestamp { get; set; } = DateTime.UtcNow; |
|||
} |
@ -0,0 +1,217 @@ |
|||
using CoreAgent.Domain.Interfaces.System; |
|||
using CoreAgent.Domain.Interfaces.System.Command; |
|||
using CoreAgent.Domain.Models.System; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CoreAgent.Infrastructure.Services.System; |
|||
|
|||
/// <summary>
|
|||
/// 设备服务实现
|
|||
/// </summary>
|
|||
public class DeviceService : IDeviceService |
|||
{ |
|||
private readonly ILogger<DeviceService> _logger; |
|||
private readonly ISystemCommandExecutor _commandExecutor; |
|||
|
|||
public DeviceService( |
|||
ILogger<DeviceService> logger, |
|||
ISystemCommandExecutor commandExecutor) |
|||
{ |
|||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); |
|||
_commandExecutor = commandExecutor ?? throw new ArgumentNullException(nameof(commandExecutor)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取设备序列号(SN)
|
|||
/// </summary>
|
|||
/// <returns>设备信息</returns>
|
|||
public async Task<DeviceInfo> GetSerialNumberAsync() |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogDebug("开始获取设备序列号"); |
|||
|
|||
// 根据操作系统选择不同的命令
|
|||
string command = GetSerialNumberCommand(); |
|||
|
|||
var result = await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource(), 5000); |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
var serialNumber = ParseSerialNumber(result.Output); |
|||
if (serialNumber != null) |
|||
{ |
|||
_logger.LogInformation("成功获取设备序列号: {SerialNumber}", serialNumber); |
|||
|
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = true, |
|||
SerialNumber = serialNumber, |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("解析设备序列号失败,输出内容: {Output}", result.Output); |
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = false, |
|||
SerialNumber = "UNKNOWN", |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogError("获取设备序列号失败: {Error}", result.Error); |
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = false, |
|||
SerialNumber = "UNKNOWN", |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取设备序列号时发生异常"); |
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = false, |
|||
SerialNumber = "ERROR", |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取设备序列号(SN)- 同步版本
|
|||
/// </summary>
|
|||
/// <returns>设备信息</returns>
|
|||
public DeviceInfo GetSerialNumber() |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogDebug("开始获取设备序列号(同步)"); |
|||
|
|||
// 根据操作系统选择不同的命令
|
|||
string command = GetSerialNumberCommand(); |
|||
|
|||
// 使用同步方式执行命令
|
|||
var task = _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource(), 5000); |
|||
task.Wait(); |
|||
var result = task.Result; |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
var serialNumber = ParseSerialNumber(result.Output); |
|||
if (serialNumber != null) |
|||
{ |
|||
_logger.LogInformation("成功获取设备序列号: {SerialNumber}", serialNumber); |
|||
|
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = true, |
|||
SerialNumber = serialNumber, |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("解析设备序列号失败,输出内容: {Output}", result.Output); |
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = false, |
|||
SerialNumber = "UNKNOWN", |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogError("获取设备序列号失败: {Error}", result.Error); |
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = false, |
|||
SerialNumber = "UNKNOWN", |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取设备序列号时发生异常"); |
|||
return new DeviceInfo |
|||
{ |
|||
IsSuccess = false, |
|||
SerialNumber = "ERROR", |
|||
Timestamp = DateTime.UtcNow |
|||
}; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据操作系统获取序列号命令
|
|||
/// </summary>
|
|||
/// <returns>命令字符串</returns>
|
|||
private string GetSerialNumberCommand() |
|||
{ |
|||
if (OperatingSystem.IsWindows()) |
|||
{ |
|||
// Windows系统获取序列号命令
|
|||
return "wmic bios get serialnumber /value"; |
|||
} |
|||
else if (OperatingSystem.IsLinux()) |
|||
{ |
|||
// Linux系统获取序列号命令
|
|||
return "smartctl -i /dev/nvme0n1|grep Serial"; |
|||
} |
|||
else |
|||
{ |
|||
// 其他系统使用通用命令
|
|||
return "echo UNKNOWN"; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 解析序列号输出
|
|||
/// </summary>
|
|||
/// <param name="output">命令输出</param>
|
|||
/// <returns>解析后的序列号,失败时返回null</returns>
|
|||
private string? ParseSerialNumber(string output) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(output)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
// 清理输出内容
|
|||
var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); |
|||
|
|||
foreach (var line in lines) |
|||
{ |
|||
var trimmedLine = line.Trim(); |
|||
|
|||
if (OperatingSystem.IsWindows()) |
|||
{ |
|||
// Windows输出格式: SerialNumber=XXXXXXXX
|
|||
if (trimmedLine.StartsWith("SerialNumber=", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var serialNumber = trimmedLine.Substring("SerialNumber=".Length).Trim(); |
|||
return string.IsNullOrWhiteSpace(serialNumber) ? null : serialNumber; |
|||
} |
|||
} |
|||
else if (OperatingSystem.IsLinux()) |
|||
{ |
|||
// Linux输出格式: Serial Number: xxxxxxxx
|
|||
if (trimmedLine.StartsWith("Serial Number:", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var serialNumber = trimmedLine.Substring("Serial Number:".Length).Trim(); |
|||
return string.IsNullOrWhiteSpace(serialNumber) ? null : serialNumber; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
Loading…
Reference in new issue