diff --git a/CoreAgent.API/Controllers/SystemController.cs b/CoreAgent.API/Controllers/SystemController.cs
new file mode 100644
index 0000000..df86215
--- /dev/null
+++ b/CoreAgent.API/Controllers/SystemController.cs
@@ -0,0 +1,34 @@
+using CoreAgent.Application.Commands.System;
+using CoreAgent.Domain.Models.System;
+using MediatR;
+using Microsoft.AspNetCore.Mvc;
+
+namespace CoreAgent.API.Controllers;
+
+///
+/// 系统控制器
+///
+public class SystemController : BaseApiController
+{
+ public SystemController(IMediator mediator, ILogger logger)
+ : base(mediator, logger)
+ {
+ }
+
+ ///
+ /// 获取设备序列号(SN)
+ ///
+ /// 设备信息
+ [HttpGet("serial-number")]
+ public async Task GetSerialNumber()
+ {
+ _logger.LogInformation("收到获取设备序列号请求");
+
+ var command = new GetSerialNumberCommand();
+ var result = await _mediator.Send(command);
+
+ _logger.LogInformation("成功返回设备序列号: {SerialNumber}", result.Data?.SerialNumber);
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.Application/Commands/System/GetSerialNumberCommand.cs b/CoreAgent.Application/Commands/System/GetSerialNumberCommand.cs
new file mode 100644
index 0000000..932e356
--- /dev/null
+++ b/CoreAgent.Application/Commands/System/GetSerialNumberCommand.cs
@@ -0,0 +1,13 @@
+using CoreAgent.Domain.Models.Common;
+using CoreAgent.Domain.Models.System;
+using MediatR;
+
+namespace CoreAgent.Application.Commands.System;
+
+///
+/// 获取设备序列号命令
+///
+public class GetSerialNumberCommand : IRequest>
+{
+ // 命令不需要额外参数,直接获取当前设备的序列号
+}
\ No newline at end of file
diff --git a/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs b/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs
index 403f520..3061c7b 100644
--- a/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs
+++ b/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs
@@ -4,6 +4,7 @@ using CoreAgent.Domain.Models.Common;
using CoreAgent.Domain.Models.Network;
using MediatR;
using Microsoft.Extensions.Logging;
+using System.Net;
namespace CoreAgent.Application.Handlers.CellularNetwork;
@@ -43,7 +44,7 @@ public class StartCellularNetworkCommandHandler : IRequestHandler.Error(
result.ErrorMessage,
"NETWORK_START_ERROR",
- System.Net.HttpStatusCode.BadRequest);
+ HttpStatusCode.BadRequest);
}
}
catch (Exception ex)
@@ -52,7 +53,7 @@ public class StartCellularNetworkCommandHandler : IRequestHandler.Error(
$"启动蜂窝网络失败: {ex.Message}",
"INTERNAL_ERROR",
- System.Net.HttpStatusCode.InternalServerError);
+ HttpStatusCode.InternalServerError);
}
}
}
\ No newline at end of file
diff --git a/CoreAgent.Application/Handlers/CellularNetwork/StopCellularNetworkCommandHandler.cs b/CoreAgent.Application/Handlers/CellularNetwork/StopCellularNetworkCommandHandler.cs
index 648ffd6..6beb7e6 100644
--- a/CoreAgent.Application/Handlers/CellularNetwork/StopCellularNetworkCommandHandler.cs
+++ b/CoreAgent.Application/Handlers/CellularNetwork/StopCellularNetworkCommandHandler.cs
@@ -3,6 +3,7 @@ using CoreAgent.Domain.Interfaces.Network;
using CoreAgent.Domain.Models.Common;
using MediatR;
using Microsoft.Extensions.Logging;
+using System.Net;
namespace CoreAgent.Application.Handlers.CellularNetwork;
@@ -42,7 +43,7 @@ public class StopCellularNetworkCommandHandler : IRequestHandler.Error(
result.ErrorMessage,
"NETWORK_STOP_ERROR",
- System.Net.HttpStatusCode.BadRequest);
+ HttpStatusCode.BadRequest);
}
}
catch (Exception ex)
@@ -51,7 +52,7 @@ public class StopCellularNetworkCommandHandler : IRequestHandler.Error(
$"停止蜂窝网络失败: {ex.Message}",
"INTERNAL_ERROR",
- System.Net.HttpStatusCode.InternalServerError);
+ HttpStatusCode.InternalServerError);
}
}
}
\ No newline at end of file
diff --git a/CoreAgent.Application/Handlers/NetworkConfig/Commands/CreateNetworkConfigurationCommandHandler.cs b/CoreAgent.Application/Handlers/NetworkConfig/Commands/CreateNetworkConfigurationCommandHandler.cs
index 5ffb2c3..1c4e42a 100644
--- a/CoreAgent.Application/Handlers/NetworkConfig/Commands/CreateNetworkConfigurationCommandHandler.cs
+++ b/CoreAgent.Application/Handlers/NetworkConfig/Commands/CreateNetworkConfigurationCommandHandler.cs
@@ -1,4 +1,5 @@
using System;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using CoreAgent.Application.Commands.NetworkConfig;
@@ -63,7 +64,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult.Error(
"配置键已存在",
"CONFIG_KEY_EXISTS",
- System.Net.HttpStatusCode.Conflict);
+ HttpStatusCode.Conflict);
}
}
catch (Exception ex)
@@ -72,7 +73,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult.Error(
$"创建网络配置失败: {ex.Message}",
"INTERNAL_ERROR",
- System.Net.HttpStatusCode.InternalServerError);
+ HttpStatusCode.InternalServerError);
}
}
}
diff --git a/CoreAgent.Application/Handlers/NetworkConfig/Commands/DeleteNetworkConfigurationCommandHandler.cs b/CoreAgent.Application/Handlers/NetworkConfig/Commands/DeleteNetworkConfigurationCommandHandler.cs
index 55f47c9..6e83b28 100644
--- a/CoreAgent.Application/Handlers/NetworkConfig/Commands/DeleteNetworkConfigurationCommandHandler.cs
+++ b/CoreAgent.Application/Handlers/NetworkConfig/Commands/DeleteNetworkConfigurationCommandHandler.cs
@@ -1,4 +1,5 @@
using System;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using CoreAgent.Application.Commands.NetworkConfig;
@@ -55,7 +56,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult.Error(
"未找到要删除的网络配置",
"CONFIG_NOT_FOUND",
- System.Net.HttpStatusCode.NotFound);
+ HttpStatusCode.NotFound);
}
}
catch (Exception ex)
@@ -64,7 +65,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult.Error(
$"删除网络配置失败: {ex.Message}",
"INTERNAL_ERROR",
- System.Net.HttpStatusCode.InternalServerError);
+ HttpStatusCode.InternalServerError);
}
}
}
diff --git a/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetAllNetworkConfigurationsQueryHandler.cs b/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetAllNetworkConfigurationsQueryHandler.cs
index 460c60a..8ffbd09 100644
--- a/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetAllNetworkConfigurationsQueryHandler.cs
+++ b/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetAllNetworkConfigurationsQueryHandler.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using CoreAgent.Application.Commands.NetworkConfig;
@@ -55,7 +56,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult>.Error(
$"获取所有网络配置失败: {ex.Message}",
"INTERNAL_ERROR",
- System.Net.HttpStatusCode.InternalServerError);
+ HttpStatusCode.InternalServerError);
}
}
}
diff --git a/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetNetworkConfigurationByKeyQueryHandler.cs b/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetNetworkConfigurationByKeyQueryHandler.cs
index 88d2e92..2373c7a 100644
--- a/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetNetworkConfigurationByKeyQueryHandler.cs
+++ b/CoreAgent.Application/Handlers/NetworkConfig/Commands/GetNetworkConfigurationByKeyQueryHandler.cs
@@ -1,4 +1,5 @@
using System;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using CoreAgent.Application.Commands.NetworkConfig;
@@ -50,7 +51,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult.Error(
$"未找到网络配置: {request.ConfigKey}",
"CONFIG_NOT_FOUND",
- System.Net.HttpStatusCode.NotFound);
+ HttpStatusCode.NotFound);
}
_logger.LogInformation("成功获取网络配置: {ConfigKey}", request.ConfigKey);
@@ -62,7 +63,7 @@ namespace CoreAgent.Application.Handlers.NetworkConfig.Commands
return ApiActionResult.Error(
$"获取网络配置失败: {ex.Message}",
"INTERNAL_ERROR",
- System.Net.HttpStatusCode.InternalServerError);
+ HttpStatusCode.InternalServerError);
}
}
}
diff --git a/CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs b/CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs
new file mode 100644
index 0000000..249c697
--- /dev/null
+++ b/CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs
@@ -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;
+
+///
+/// 获取设备序列号命令处理器
+///
+public class GetSerialNumberCommandHandler : IRequestHandler>
+{
+ private readonly IDeviceService _deviceService;
+ private readonly ILogger _logger;
+
+ public GetSerialNumberCommandHandler(
+ IDeviceService deviceService,
+ ILogger logger)
+ {
+ _deviceService = deviceService ?? throw new ArgumentNullException(nameof(deviceService));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ public async Task> Handle(GetSerialNumberCommand request, CancellationToken cancellationToken)
+ {
+ try
+ {
+ _logger.LogInformation("开始处理获取设备序列号命令");
+
+ var deviceInfo = await _deviceService.GetSerialNumberAsync();
+
+ if (deviceInfo.IsSuccess)
+ {
+ _logger.LogInformation("成功获取设备序列号: {SerialNumber}", deviceInfo.SerialNumber);
+ return ApiActionResult.Ok(deviceInfo, "获取设备序列号成功");
+ }
+ else
+ {
+ _logger.LogWarning("获取设备序列号失败,返回的序列号: {SerialNumber}", deviceInfo.SerialNumber);
+ return ApiActionResult.Error("获取设备序列号失败", "DEVICE_SN_NOT_FOUND");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "处理获取设备序列号命令时发生异常");
+ return ApiActionResult.Error("获取设备序列号失败", "DEVICE_SN_ERROR");
+ }
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.Domain/Interfaces/System/IDeviceService.cs b/CoreAgent.Domain/Interfaces/System/IDeviceService.cs
new file mode 100644
index 0000000..bf999af
--- /dev/null
+++ b/CoreAgent.Domain/Interfaces/System/IDeviceService.cs
@@ -0,0 +1,21 @@
+using CoreAgent.Domain.Models.System;
+
+namespace CoreAgent.Domain.Interfaces.System;
+
+///
+/// 设备服务接口
+///
+public interface IDeviceService
+{
+ ///
+ /// 获取设备序列号(SN)
+ ///
+ /// 设备信息
+ Task GetSerialNumberAsync();
+
+ ///
+ /// 获取设备序列号(SN)- 同步版本
+ ///
+ /// 设备信息
+ DeviceInfo GetSerialNumber();
+}
\ No newline at end of file
diff --git a/CoreAgent.Domain/Models/System/DeviceInfo.cs b/CoreAgent.Domain/Models/System/DeviceInfo.cs
new file mode 100644
index 0000000..cab3cf9
--- /dev/null
+++ b/CoreAgent.Domain/Models/System/DeviceInfo.cs
@@ -0,0 +1,22 @@
+namespace CoreAgent.Domain.Models.System;
+
+///
+/// 设备信息模型
+///
+public class DeviceInfo
+{
+ ///
+ /// 是否成功获取到序列号
+ ///
+ public bool IsSuccess { get; set; }
+
+ ///
+ /// 设备序列号(SN)
+ ///
+ public string SerialNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取时间
+ ///
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+}
\ No newline at end of file
diff --git a/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs b/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs
index c37e5a8..5bd9615 100644
--- a/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs
+++ b/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs
@@ -1,11 +1,13 @@
using CoreAgent.Domain.Interfaces;
using CoreAgent.Domain.Interfaces.Network;
+using CoreAgent.Domain.Interfaces.System;
using CoreAgent.Domain.Interfaces.System.Command;
using CoreAgent.Infrastructure.Command.Factories;
using CoreAgent.Infrastructure.Contexts;
using CoreAgent.Infrastructure.Repositories;
using CoreAgent.Infrastructure.Services;
using CoreAgent.Infrastructure.Services.Network;
+using CoreAgent.Infrastructure.Services.System;
using CoreAgent.ProtocolClient.Interfaces;
using CoreAgent.ProtocolClient.ProtocolEngineCore;
using Microsoft.Extensions.DependencyInjection;
@@ -57,6 +59,9 @@ public static class CommandServiceExtensions
services.AddScoped();
services.AddScoped();
services.AddScoped();
+
+ // 注册系统服务
+ services.AddScoped();
return services;
}
diff --git a/CoreAgent.Infrastructure/Services/Network/NetworkProtocolLogObserver.cs b/CoreAgent.Infrastructure/Services/Network/NetworkProtocolLogObserver.cs
index 760a56c..89e3454 100644
--- a/CoreAgent.Infrastructure/Services/Network/NetworkProtocolLogObserver.cs
+++ b/CoreAgent.Infrastructure/Services/Network/NetworkProtocolLogObserver.cs
@@ -50,7 +50,7 @@ namespace CoreAgent.Infrastructure.Services.Network
var webSocketLogs = logList.Select(log => new MessageTransferProtocolLog
{
Id = log.Id,
- LayerType = log.LayerType.ToString(),
+ LayerType = (int)log.LayerType,
MessageDetailJson = log.MessageDetailJson,
CellID = log.CellID,
IMSI = log.IMSI,
diff --git a/CoreAgent.Infrastructure/Services/System/DeviceService.cs b/CoreAgent.Infrastructure/Services/System/DeviceService.cs
new file mode 100644
index 0000000..ea721bf
--- /dev/null
+++ b/CoreAgent.Infrastructure/Services/System/DeviceService.cs
@@ -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;
+
+///
+/// 设备服务实现
+///
+public class DeviceService : IDeviceService
+{
+ private readonly ILogger _logger;
+ private readonly ISystemCommandExecutor _commandExecutor;
+
+ public DeviceService(
+ ILogger logger,
+ ISystemCommandExecutor commandExecutor)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _commandExecutor = commandExecutor ?? throw new ArgumentNullException(nameof(commandExecutor));
+ }
+
+ ///
+ /// 获取设备序列号(SN)
+ ///
+ /// 设备信息
+ public async Task 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
+ };
+ }
+ }
+
+ ///
+ /// 获取设备序列号(SN)- 同步版本
+ ///
+ /// 设备信息
+ 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
+ };
+ }
+ }
+
+ ///
+ /// 根据操作系统获取序列号命令
+ ///
+ /// 命令字符串
+ 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";
+ }
+ }
+
+ ///
+ /// 解析序列号输出
+ ///
+ /// 命令输出
+ /// 解析后的序列号,失败时返回null
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/CoreAgent.WebSocketTransport/Models/MessageTransferProtocolLog.cs b/CoreAgent.WebSocketTransport/Models/MessageTransferProtocolLog.cs
index c063043..c1264f3 100644
--- a/CoreAgent.WebSocketTransport/Models/MessageTransferProtocolLog.cs
+++ b/CoreAgent.WebSocketTransport/Models/MessageTransferProtocolLog.cs
@@ -21,7 +21,7 @@ namespace CoreAgent.WebSocketTransport.Models
///
/// 协议层类型
///
- public string LayerType { get; set; } = string.Empty;
+ public int LayerType { get; set; }
///
/// 消息详情集合(JSON格式存储)
diff --git a/modify.md b/modify.md
index ab3fad4..a54ea75 100644
--- a/modify.md
+++ b/modify.md
@@ -2,6 +2,109 @@
## 2024年修改记录
+### 创建获取SN接口 - 遵循DDD设计架构
+
+**修改时间**: 2024年
+**修改文件**:
+- `CoreAgent.Domain/Models/System/DeviceInfo.cs` (新建)
+- `CoreAgent.Domain/Interfaces/System/IDeviceService.cs` (新建)
+- `CoreAgent.Infrastructure/Services/System/DeviceService.cs` (新建)
+- `CoreAgent.Application/Commands/System/GetSerialNumberCommand.cs` (新建)
+- `CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs` (新建)
+- `CoreAgent.API/Controllers/SystemController.cs` (新建)
+- `CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs`
+
+**修改内容**:
+
+1. **领域层设计**
+ - 创建 `DeviceInfo` 模型,包含 `SerialNumber` 和 `Timestamp` 字段
+ - 定义 `IDeviceService` 接口,提供获取SN的异步和同步方法
+ - 遵循DDD设计原则,接口定义在领域层
+
+2. **基础设施层实现**
+ - 实现 `DeviceService` 类,使用 `ISystemCommandExecutor` 执行系统命令
+ - 支持Windows和Linux系统,自动选择对应的命令
+ - Windows: `wmic bios get serialnumber /value`
+ - Linux: `cat /sys/class/dmi/id/product_serial`
+ - 提供完善的错误处理和日志记录
+
+3. **应用层设计**
+ - 创建 `GetSerialNumberCommand` 命令类,返回 `ApiActionResult`
+ - 实现 `GetSerialNumberCommandHandler` 处理器,返回包装后的结果
+ - 使用MediatR模式处理命令
+ - 在应用层统一处理成功和错误响应
+
+4. **API层设计**
+ - 创建 `SystemController` 控制器,继承 `BaseApiController`
+ - 提供 `GET /api/v1/system/serial-number` 接口
+ - 直接返回应用层的 `ApiActionResult` 结果
+ - 简化控制器逻辑,错误处理在应用层完成
+
+5. **依赖注入配置**
+ - 在 `CommandServiceExtensions` 中注册 `IDeviceService`
+ - 使用作用域生命周期管理
+
+6. **具体实现**:
+ ```csharp
+ // 领域模型
+ public class DeviceInfo
+ {
+ public string SerialNumber { get; set; } = string.Empty;
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+ }
+
+ // 领域接口
+ public interface IDeviceService
+ {
+ Task GetSerialNumberAsync();
+ DeviceInfo GetSerialNumber();
+ }
+
+ // 基础设施实现
+ public class DeviceService : IDeviceService
+ {
+ private readonly ISystemCommandExecutor _commandExecutor;
+
+ public async Task GetSerialNumberAsync()
+ {
+ string command = GetSerialNumberCommand();
+ var result = await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource(), 5000);
+ return ParseSerialNumber(result.Output);
+ }
+ }
+
+ // 应用层处理器
+ public async Task> Handle(GetSerialNumberCommand request, CancellationToken cancellationToken)
+ {
+ var deviceInfo = await _deviceService.GetSerialNumberAsync();
+ return ApiActionResult.Ok(deviceInfo, "获取设备序列号成功");
+ }
+
+ // API控制器
+ [HttpGet("serial-number")]
+ public async Task GetSerialNumber()
+ {
+ var command = new GetSerialNumberCommand();
+ var result = await _mediator.Send(command);
+ return result;
+ }
+ ```
+
+7. **设计优势**:
+ - **DDD架构**: 严格遵循领域驱动设计的分层架构
+ - **依赖倒置**: 高层模块依赖抽象,不依赖具体实现
+ - **单一职责**: 每个类都有明确的职责
+ - **跨平台支持**: 自动识别操作系统并使用对应命令
+ - **错误处理**: 完善的异常处理和日志记录
+ - **可测试性**: 接口抽象便于单元测试
+ - **可扩展性**: 易于添加新的设备信息获取功能
+
+**影响范围**:
+- 新增系统服务模块
+- 扩展API接口
+- 依赖注入配置更新
+- 命令处理流程扩展
+
### 创建MessageTransferProtocolLog模型解决命名冲突
**修改时间**: 2024年
@@ -746,4 +849,115 @@
- 依赖注入容器的服务解析
- 应用程序启动时的服务注册
- 中间件的实例化策略
-- 性能和内存使用优化
\ No newline at end of file
+- 性能和内存使用优化
+
+### DeviceInfo模型添加IsSuccess字段和ParseSerialNumber方法优化
+
+**修改时间**: 2024年
+**修改文件**:
+- `CoreAgent.Domain/Models/System/DeviceInfo.cs`
+- `CoreAgent.Infrastructure/Services/System/DeviceService.cs`
+- `CoreAgent.Application/Handlers/System/GetSerialNumberCommandHandler.cs`
+
+**修改内容**:
+
+1. **DeviceInfo模型添加IsSuccess字段**
+ - 添加 `bool IsSuccess { get; set; }` 属性
+ - 用于标识是否成功获取到序列号
+ - 提供更准确的成功/失败状态判断
+
+2. **ParseSerialNumber方法优化**
+ - 返回类型从 `string` 改为 `string?`(可空字符串)
+ - 失败时返回 `null` 而不是固定字符串
+ - 修复Linux系统输出格式解析:`Serial Number: xxxxxxxx`
+ - 添加更详细的注释说明返回值含义
+
+3. **DeviceService方法更新**
+ - 修改异步和同步方法中的DeviceInfo创建逻辑
+ - 根据ParseSerialNumber返回值设置IsSuccess字段
+ - 成功时设置 `IsSuccess = true`
+ - 失败时设置 `IsSuccess = false`
+ - 添加更详细的日志记录
+
+4. **GetSerialNumberCommandHandler优化**
+ - 在Handle方法中检查 `deviceInfo.IsSuccess` 字段
+ - 成功时返回 `ApiActionResult.Ok()`
+ - 失败时返回 `ApiActionResult.Error()` 并设置错误代码 `DEVICE_SN_NOT_FOUND`
+ - 提供更准确的错误信息
+
+5. **具体实现**:
+ ```csharp
+ // DeviceInfo模型
+ public class DeviceInfo
+ {
+ public bool IsSuccess { get; set; }
+ public string SerialNumber { get; set; } = string.Empty;
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+ }
+
+ // ParseSerialNumber方法
+ private string? ParseSerialNumber(string output)
+ {
+ if (string.IsNullOrWhiteSpace(output))
+ return null;
+
+ foreach (var line in lines)
+ {
+ 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;
+ }
+
+ // DeviceService中的使用
+ if (serialNumber != null)
+ {
+ return new DeviceInfo
+ {
+ IsSuccess = true,
+ SerialNumber = serialNumber,
+ Timestamp = DateTime.UtcNow
+ };
+ }
+ else
+ {
+ return new DeviceInfo
+ {
+ IsSuccess = false,
+ SerialNumber = "UNKNOWN",
+ Timestamp = DateTime.UtcNow
+ };
+ }
+
+ // GetSerialNumberCommandHandler中的使用
+ if (deviceInfo.IsSuccess)
+ {
+ return ApiActionResult.Ok(deviceInfo, "获取设备序列号成功");
+ }
+ else
+ {
+ return ApiActionResult.Error("获取设备序列号失败", "DEVICE_SN_NOT_FOUND");
+ }
+ ```
+
+6. **设计优势**:
+ - **准确的状态判断**:通过IsSuccess字段明确标识操作结果
+ - **更好的错误处理**:区分不同类型的失败情况
+ - **Linux兼容性**:正确解析Linux系统的序列号输出格式
+ - **空值安全**:使用可空字符串避免固定错误字符串
+ - **详细日志**:提供更丰富的日志信息便于调试
+ - **API一致性**:返回统一的ApiActionResult格式
+
+**影响范围**:
+- 设备序列号获取的准确性
+- API响应的错误处理
+- Linux系统兼容性
+- 日志记录的详细程度
+- 客户端错误处理逻辑
\ No newline at end of file