diff --git a/CoreAgent.API/Configurations/netcommand.json b/CoreAgent.API/Configurations/netcommand.json new file mode 100644 index 0000000..938dc67 --- /dev/null +++ b/CoreAgent.API/Configurations/netcommand.json @@ -0,0 +1,62 @@ +{ + "NetworkCommand": { + "DefaultRetryCount": 3, + "DefaultRetryInterval": 1000, + "NetworkCommands": [ + { + "type": 1, + "template": "network init", + "timeout": 30000, + "isEnabled": true + }, + { + "type": 1, + "template": "network check", + "timeout": 15000, + "isEnabled": true + }, + { + "type": 1, + "template": "network verify", + "timeout": 20000, + "isEnabled": true + }, + { + "type": 2, + "template": "network start", + "timeout": 25000, + "isEnabled": true + }, + { + "type": 2, + "template": "network resume", + "timeout": 20000, + "isEnabled": true + }, + { + "type": 3, + "template": "network stop", + "timeout": 8000, + "isEnabled": true + }, + { + "type": 3, + "template": "network cleanup", + "timeout": 5000, + "isEnabled": true + }, + { + "type": 4, + "template": "network status", + "timeout": 5000, + "isEnabled": true + }, + { + "type": 4, + "template": "network info", + "timeout": 5000, + "isEnabled": true + } + ] + } +} \ No newline at end of file diff --git a/CoreAgent.API/Startup.cs b/CoreAgent.API/Startup.cs index e86895c..9b6a873 100644 --- a/CoreAgent.API/Startup.cs +++ b/CoreAgent.API/Startup.cs @@ -1,9 +1,11 @@ - using System.Reflection; using Serilog; using CoreAgent.Infrastructure.Extensions.Logging; using CoreAgent.Infrastructure.Extensions.ServiceCollection; using CoreAgent.Infrastructure.Middleware.GlobalException; +using CoreAgent.Domain.Contexts; +using CoreAgent.Domain.Models.System; +using Microsoft.Extensions.Configuration; namespace CoreAgent.API { @@ -81,7 +83,12 @@ namespace CoreAgent.API .AddJsonFile($"{configurationsDirectory}/request-logging.json", optional: false, reloadOnChange: true) .AddJsonFile($"{configurationsDirectory}/request-logging.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) .AddJsonFile($"{configurationsDirectory}/api-versioning.json", optional: false, reloadOnChange: true) - .AddJsonFile($"{configurationsDirectory}/api-versioning.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); + .AddJsonFile($"{configurationsDirectory}/api-versioning.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) + .AddJsonFile($"{configurationsDirectory}/netcommand.json", optional: false, reloadOnChange: true) + .AddJsonFile($"{configurationsDirectory}/netcommand.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); + + var networkCommandConfig = builder.Configuration.GetSection("networkCommand").Get(); + CellularNetworkContext.Instance.SetNetworkCommandConfig(networkCommandConfig); return builder; } diff --git a/CoreAgent.API/logs/log-20250611.txt b/CoreAgent.API/logs/log-20250611.txt index 588bffa..9839326 100644 --- a/CoreAgent.API/logs/log-20250611.txt +++ b/CoreAgent.API/logs/log-20250611.txt @@ -355,3 +355,32 @@ System.Exception: 命令执行失败: 2025-06-11 10:55:18.651 +08:00 [INF] 蜂窝网络接口 string 启动成功 2025-06-11 10:55:18.652 +08:00 [INF] Response for POST /api/v1/CellularNetwork/start: 200 - {"data":true,"isSuccess":true,"message":"操作成功","errorCode":"","statusCode":200} 2025-06-11 10:55:18.655 +08:00 [INF] Request completed: POST /api/v1/CellularNetwork/start in 19ms with status code 200 +2025-06-11 12:01:37.925 +08:00 [INF] Logger initialized successfully +2025-06-11 12:01:37.959 +08:00 [INF] Application starting... +2025-06-11 12:01:38.940 +08:00 [INF] Application startup completed +2025-06-11 12:01:44.947 +08:00 [INF] Request started: POST /api/v1/CellularNetwork/start +2025-06-11 12:01:45.036 +08:00 [INF] 收到启动蜂窝网络请求: string +2025-06-11 12:01:45.038 +08:00 [INF] Handling request of type StartCellularNetworkCommand +2025-06-11 12:01:45.043 +08:00 [INF] 正在启动蜂窝网络接口: string +2025-06-11 12:01:45.046 +08:00 [INF] 正在启动蜂窝网络接口: string +2025-06-11 12:01:45.048 +08:00 [INF] 正在配置蜂窝网络接口: string +2025-06-11 12:01:45.533 +08:00 [ERR] 配置APN失败 +2025-06-11 12:01:45.535 +08:00 [ERR] 配置蜂窝网络参数失败 +2025-06-11 12:01:45.536 +08:00 [WRN] 蜂窝网络接口 string 启动失败 +2025-06-11 12:01:45.557 +08:00 [INF] Response for POST /api/v1/CellularNetwork/start: 200 - {"data":false,"isSuccess":true,"message":"操作成功","errorCode":"","statusCode":200} +2025-06-11 12:01:45.562 +08:00 [INF] Request completed: POST /api/v1/CellularNetwork/start in 620ms with status code 200 +2025-06-11 17:26:37.953 +08:00 [INF] Logger initialized successfully +2025-06-11 17:26:37.990 +08:00 [INF] Application starting... +2025-06-11 17:26:38.963 +08:00 [INF] Application startup completed +2025-06-11 17:35:10.311 +08:00 [INF] Request started: POST /api/v1/CellularNetwork/start +2025-06-11 17:35:10.395 +08:00 [INF] 收到启动蜂窝网络请求: string +2025-06-11 17:35:10.397 +08:00 [INF] Handling request of type StartCellularNetworkCommand +2025-06-11 17:35:10.401 +08:00 [INF] 正在启动蜂窝网络接口: string +2025-06-11 17:35:41.810 +08:00 [INF] Logger initialized successfully +2025-06-11 17:35:41.873 +08:00 [INF] Application starting... +2025-06-11 17:35:42.238 +08:00 [INF] Application startup completed +2025-06-11 17:35:48.997 +08:00 [INF] Request started: POST /api/v1/CellularNetwork/start +2025-06-11 17:35:49.098 +08:00 [INF] 收到启动蜂窝网络请求: string +2025-06-11 17:35:49.102 +08:00 [INF] Handling request of type StartCellularNetworkCommand +2025-06-11 17:35:49.108 +08:00 [INF] 正在启动蜂窝网络接口: string +2025-06-11 17:36:00.832 +08:00 [INF] 正在启动蜂窝网络接口: string diff --git a/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs b/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs index 7c96de3..3beea10 100644 --- a/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs +++ b/CoreAgent.Application/Handlers/CellularNetwork/StartCellularNetworkCommandHandler.cs @@ -34,14 +34,14 @@ public class StartCellularNetworkCommandHandler : IRequestHandler +/// 蜂窝网络领域上下文 +/// +public class CellularNetworkContext +{ + private static readonly Lazy _instance = new(() => new CellularNetworkContext()); + private readonly object _lock = new(); + private readonly Dictionary _networkStates = new(); + private NetworkCommandConfig _networkCommandConfig; + + /// + /// 获取单例实例 + /// + public static CellularNetworkContext Instance => _instance.Value; + + private CellularNetworkContext() { } + + /// + /// 设置网络命令配置 + /// + /// 网络命令配置 + public void SetNetworkCommandConfig(NetworkCommandConfig config) + { + lock (_lock) + { + _networkCommandConfig = config ?? throw new ArgumentNullException(nameof(config)); + } + } + + /// + /// 获取网络命令配置 + /// + /// 网络命令配置 + public NetworkCommandConfig GetNetworkCommandConfig() + { + lock (_lock) + { + return _networkCommandConfig ?? throw new InvalidOperationException("网络命令配置未初始化"); + } + } + + /// + /// 获取指定类型的命令配置 + /// + /// 命令类型 + /// 命令配置列表 + public List GetCommandsByType(NetworkCommandType type) + { + lock (_lock) + { + return _networkCommandConfig?.GetCommandsByType(type) ?? new List(); + } + } + + /// + /// 获取所有命令类型 + /// + /// 命令类型数组 + public NetworkCommandType[] GetCommandTypes() + { + lock (_lock) + { + return _networkCommandConfig?.GetCommandTypes() ?? Array.Empty(); + } + } + + /// + /// 获取或创建网络状态 + /// + /// 网络接口名称 + /// 网络状态 + public CellularNetworkState GetOrCreateNetworkState(string interfaceName) + { + lock (_lock) + { + if (!_networkStates.TryGetValue(interfaceName, out var state)) + { + state = new CellularNetworkState(interfaceName); + _networkStates[interfaceName] = state; + } + return state; + } + } + + /// + /// 移除网络状态 + /// + /// 网络接口名称 + public void RemoveNetworkState(string interfaceName) + { + lock (_lock) + { + _networkStates.Remove(interfaceName); + } + } + + /// + /// 获取所有网络状态 + /// + /// 所有网络状态的集合 + public IReadOnlyCollection GetAllNetworkStates() + { + lock (_lock) + { + return _networkStates.Values.ToList().AsReadOnly(); + } + } +} + +/// +/// 蜂窝网络状态 +/// +public class CellularNetworkState +{ + /// + /// 网络接口名称 + /// + public string InterfaceName { get; } + + /// + /// 是否已初始化 + /// + public bool IsInitialized { get; private set; } + + /// + /// 最后启动时间 + /// + public DateTime? LastStartTime { get; private set; } + + /// + /// 最后停止时间 + /// + public DateTime? LastStopTime { get; private set; } + + /// + /// 当前运行状态 + /// + public NetworkStatus CurrentStatus { get; private set; } + + /// + /// 当前信号强度 + /// + public SignalStrength CurrentSignalStrength { get; private set; } + + /// + /// 当前网络类型 + /// + public NetworkType CurrentNetworkType { get; private set; } + + /// + /// 当前发射功率 + /// + public int CurrentTransmitPower { get; private set; } + + /// + /// 网络配置 + /// + public CellularNetworkConfig Config { get; private set; } + + public CellularNetworkState(string interfaceName) + { + InterfaceName = interfaceName; + IsInitialized = false; + CurrentStatus = NetworkStatus.Unknown; + CurrentSignalStrength = SignalStrength.NoSignal; + CurrentNetworkType = NetworkType.Unknown; + CurrentTransmitPower = 0; + } + + /// + /// 更新网络状态 + /// + public void UpdateStatus(NetworkStatus status) + { + CurrentStatus = status; + } + + /// + /// 更新信号强度 + /// + public void UpdateSignalStrength(SignalStrength strength) + { + CurrentSignalStrength = strength; + } + + /// + /// 更新网络类型 + /// + public void UpdateNetworkType(NetworkType type) + { + CurrentNetworkType = type; + } + + /// + /// 更新发射功率 + /// + public void UpdateTransmitPower(int power) + { + CurrentTransmitPower = power; + } + + /// + /// 更新网络配置 + /// + public void UpdateConfig(CellularNetworkConfig config) + { + Config = config; + } + + /// + /// 标记为已启动 + /// + public void MarkAsStarted() + { + IsInitialized = true; + LastStartTime = DateTime.Now; + CurrentStatus = NetworkStatus.Connected; + } + + /// + /// 标记为已停止 + /// + public void MarkAsStopped() + { + IsInitialized = false; + LastStopTime = DateTime.Now; + CurrentStatus = NetworkStatus.Disconnected; + CurrentSignalStrength = SignalStrength.NoSignal; + CurrentNetworkType = NetworkType.Unknown; + CurrentTransmitPower = 0; + } +} \ No newline at end of file diff --git a/CoreAgent.Domain/Interfaces/Network/ICellularNetworkService.cs b/CoreAgent.Domain/Interfaces/Network/ICellularNetworkService.cs index 512c639..a75754a 100644 --- a/CoreAgent.Domain/Interfaces/Network/ICellularNetworkService.cs +++ b/CoreAgent.Domain/Interfaces/Network/ICellularNetworkService.cs @@ -21,41 +21,6 @@ public interface ICellularNetworkService /// 网络接口名称 /// 停止结果 Task StopAsync(string interfaceName); - - /// - /// 获取网络状态 - /// - /// 网络接口名称 - /// 网络状态信息 - Task GetNetworkStatusAsync(string interfaceName); - - /// - /// 获取信号强度 - /// - /// 网络接口名称 - /// 信号强度信息 - Task GetSignalStrengthAsync(string interfaceName); - - /// - /// 获取网络类型 - /// - /// 网络接口名称 - /// 网络类型信息 - Task GetNetworkTypeAsync(string interfaceName); - - /// - /// 设置发射功率 - /// - /// 网络接口名称 - /// 功率等级(0-100) - /// 设置结果 - Task SetTransmitPowerAsync(string interfaceName, int powerLevel); - - /// - /// 获取全局状态 - /// - /// 全局状态信息 - Task GetGlobalStatusAsync(); } /// diff --git a/CoreAgent.Domain/Interfaces/Network/INetworkConfigurator.cs b/CoreAgent.Domain/Interfaces/Network/INetworkConfigurator.cs new file mode 100644 index 0000000..0313dd8 --- /dev/null +++ b/CoreAgent.Domain/Interfaces/Network/INetworkConfigurator.cs @@ -0,0 +1,25 @@ +using CoreAgent.Domain.Models.Network; + +namespace CoreAgent.Domain.Interfaces.Network; + +/// +/// 网络配置器接口 +/// +public interface INetworkConfigurator +{ + /// + /// 配置网络参数 + /// + /// 网络接口名称 + /// 网络配置 + /// 配置结果 + Task ConfigureAsync(string interfaceName, CellularNetworkConfig config); + + /// + /// 设置发射功率 + /// + /// 网络接口名称 + /// 功率等级(0-100) + /// 设置结果 + Task SetTransmitPowerAsync(string interfaceName, int powerLevel); +} \ No newline at end of file diff --git a/CoreAgent.Domain/Interfaces/Network/INetworkStatusProvider.cs b/CoreAgent.Domain/Interfaces/Network/INetworkStatusProvider.cs new file mode 100644 index 0000000..8c03289 --- /dev/null +++ b/CoreAgent.Domain/Interfaces/Network/INetworkStatusProvider.cs @@ -0,0 +1,36 @@ +using CoreAgent.Domain.Models.Network; + +namespace CoreAgent.Domain.Interfaces.Network; + +/// +/// 网络状态提供者接口 +/// +public interface INetworkStatusProvider +{ + /// + /// 获取网络状态 + /// + /// 网络接口名称 + /// 网络状态信息 + Task GetNetworkStatusAsync(string interfaceName); + + /// + /// 获取信号强度 + /// + /// 网络接口名称 + /// 信号强度信息 + Task GetSignalStrengthAsync(string interfaceName); + + /// + /// 获取网络类型 + /// + /// 网络接口名称 + /// 网络类型信息 + Task GetNetworkTypeAsync(string interfaceName); + + /// + /// 获取全局状态 + /// + /// 全局状态信息 + Task GetGlobalStatusAsync(); +} \ No newline at end of file diff --git a/CoreAgent.Domain/Models/System/CommandTemplateConfig.cs b/CoreAgent.Domain/Models/System/CommandTemplateConfig.cs new file mode 100644 index 0000000..0b4d850 --- /dev/null +++ b/CoreAgent.Domain/Models/System/CommandTemplateConfig.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; + +namespace CoreAgent.Domain.Models.System; + +/// +/// 命令模板配置 +/// +public class CommandTemplateConfig +{ + /// + /// 命令类型 + /// + [JsonPropertyName("type")] + public NetworkCommandType Type { get; set; } + + /// + /// 命令模板 + /// + [JsonPropertyName("template")] + public string Template { get; set; } + + /// + /// 超时时间(毫秒) + /// + [JsonPropertyName("timeout")] + public int Timeout { get; set; } + + /// + /// 是否启用 + /// + [JsonPropertyName("isEnabled")] + public bool IsEnabled { get; set; } = true; +} \ No newline at end of file diff --git a/CoreAgent.Domain/Models/System/NetworkCommandConfig.cs b/CoreAgent.Domain/Models/System/NetworkCommandConfig.cs new file mode 100644 index 0000000..47c6311 --- /dev/null +++ b/CoreAgent.Domain/Models/System/NetworkCommandConfig.cs @@ -0,0 +1,46 @@ +using System.Text.Json.Serialization; + +namespace CoreAgent.Domain.Models.System; + +/// +/// 网络命令配置 +/// +public class NetworkCommandConfig +{ + /// + /// 默认重试次数 + /// + [JsonPropertyName("DefaultRetryCount")] + public int DefaultRetryCount { get; set; } + + /// + /// 默认重试间隔(毫秒) + /// + [JsonPropertyName("DefaultRetryInterval")] + public int DefaultRetryInterval { get; set; } + + /// + /// 网络命令配置列表 + /// + [JsonPropertyName("NetworkCommands")] + public List NetworkCommands { get; set; } + + /// + /// 获取指定类型的命令配置 + /// + /// 命令类型 + /// 命令配置列表 + public List GetCommandsByType(NetworkCommandType type) + { + return NetworkCommands?.Where(c => c.Type == type).ToList() ?? new List(); + } + + /// + /// 获取所有命令类型 + /// + /// 命令类型数组 + public NetworkCommandType[] GetCommandTypes() + { + return NetworkCommands?.Select(c => c.Type).Distinct().ToArray() ?? Array.Empty(); + } +} \ No newline at end of file diff --git a/CoreAgent.Domain/Models/System/NetworkCommandType.cs b/CoreAgent.Domain/Models/System/NetworkCommandType.cs new file mode 100644 index 0000000..8933cd7 --- /dev/null +++ b/CoreAgent.Domain/Models/System/NetworkCommandType.cs @@ -0,0 +1,27 @@ +namespace CoreAgent.Domain.Models.System; + +/// +/// 网络命令类型 +/// +public enum NetworkCommandType +{ + /// + /// 初始化命令 + /// + Initialize = 1, + + /// + /// 启动命令 + /// + Start = 2, + + /// + /// 停止命令 + /// + Stop = 3, + + /// + /// 状态命令 + /// + Status = 4 +} \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs b/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs index a6bfb6a..fadb9f7 100644 --- a/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs +++ b/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs @@ -1,7 +1,7 @@ using CoreAgent.Domain.Interfaces.Network; using CoreAgent.Domain.Interfaces.System.Command; using CoreAgent.Infrastructure.Command.Factories; -using CoreAgent.Infrastructure.Services; +using CoreAgent.Infrastructure.Services.Network; using Microsoft.Extensions.DependencyInjection; namespace CoreAgent.Infrastructure.Extensions.ServiceCollection; @@ -28,8 +28,15 @@ public static class CommandServiceExtensions return factory.CreateExecutor(); }); - // 注册 ICellularNetworkService + // 注册网络配置器 + services.AddScoped(); + + // 注册网络状态提供者 + services.AddScoped(); + + // 注册网络服务 services.AddScoped(); + return services; } } \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/CellularNetworkService.cs b/CoreAgent.Infrastructure/Services/CellularNetworkService.cs deleted file mode 100644 index 9019e34..0000000 --- a/CoreAgent.Infrastructure/Services/CellularNetworkService.cs +++ /dev/null @@ -1,380 +0,0 @@ -using CoreAgent.Domain.Interfaces.Network; -using CoreAgent.Domain.Interfaces.System.Command; -using CoreAgent.Domain.Models.Network; -using CoreAgent.Domain.Models.System; -using CoreAgent.Infrastructure.Command.Factories; -using Microsoft.Extensions.Logging; -using System.Diagnostics; - -namespace CoreAgent.Infrastructure.Services; - -/// -/// 蜂窝网络服务实现 -/// -public class CellularNetworkService : ICellularNetworkService -{ - private readonly ILogger _logger; - private readonly CellularNetworkGlobalStatus _globalStatus; - private readonly ISystemCommandExecutorFactory _commandExecutorFactory; - private static readonly SemaphoreSlim _startLock = new SemaphoreSlim(1, 1); - - public CellularNetworkService( - ILogger logger, - ISystemCommandExecutorFactory commandExecutorFactory) - { - _logger = logger; - _commandExecutorFactory = commandExecutorFactory; - _globalStatus = new CellularNetworkGlobalStatus - { - IsInitialized = false, - CurrentStatus = NetworkStatus.Unknown, - CurrentSignalStrength = SignalStrength.NoSignal, - CurrentNetworkType = NetworkType.Unknown, - CurrentTransmitPower = 0 - }; - } - - public async Task StartAsync(string interfaceName, CellularNetworkConfig config) - { - try - { - // 使用信号量确保只能启动一次 - if (!await _startLock.WaitAsync(TimeSpan.FromSeconds(5))) - { - _logger.LogWarning("蜂窝网络启动操作被锁定,可能已有其他启动操作正在进行"); - return false; - } - - try - { - if (_globalStatus.IsInitialized) - { - _logger.LogWarning("蜂窝网络已经初始化,不能重复启动"); - return false; - } - - _logger.LogInformation("正在启动蜂窝网络接口: {InterfaceName}", interfaceName); - - // 1. 配置网络参数 - var configResult = await ConfigureNetworkAsync(interfaceName, config); - if (!configResult) - { - _logger.LogError("配置蜂窝网络参数失败"); - return false; - } - - // 2. 启动网络接口 - var startResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" admin=enable"); - if (!startResult) - { - _logger.LogError("启动蜂窝网络接口失败"); - return false; - } - - // 3. 等待网络连接 - var connected = await WaitForConnectionAsync(interfaceName); - if (!connected) - { - _logger.LogError("蜂窝网络连接超时"); - return false; - } - - // 4. 更新全局状态 - _globalStatus.IsInitialized = true; - _globalStatus.LastStartTime = DateTime.Now; - _globalStatus.CurrentStatus = NetworkStatus.Connected; - _globalStatus.CurrentSignalStrength = await GetSignalStrengthAsync(interfaceName); - _globalStatus.CurrentNetworkType = await GetNetworkTypeAsync(interfaceName); - - _logger.LogInformation("蜂窝网络接口 {InterfaceName} 启动成功", interfaceName); - return true; - } - finally - { - _startLock.Release(); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "启动蜂窝网络接口 {InterfaceName} 失败", interfaceName); - return false; - } - } - - public async Task StopAsync(string interfaceName) - { - try - { - if (!_globalStatus.IsInitialized) - { - _logger.LogWarning("蜂窝网络未初始化,无需停止"); - return true; - } - - _logger.LogInformation("正在停止蜂窝网络接口: {InterfaceName}", interfaceName); - - // 1. 停止网络接口 - var stopResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" admin=disable"); - if (!stopResult) - { - _logger.LogError("停止蜂窝网络接口失败"); - return false; - } - - // 2. 更新全局状态 - _globalStatus.IsInitialized = false; - _globalStatus.LastStopTime = DateTime.Now; - _globalStatus.CurrentStatus = NetworkStatus.Disconnected; - _globalStatus.CurrentSignalStrength = SignalStrength.NoSignal; - _globalStatus.CurrentNetworkType = NetworkType.Unknown; - _globalStatus.CurrentTransmitPower = 0; - - _logger.LogInformation("蜂窝网络接口 {InterfaceName} 停止成功", interfaceName); - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "停止蜂窝网络接口 {InterfaceName} 失败", interfaceName); - return false; - } - } - - public async Task GetNetworkStatusAsync(string interfaceName) - { - try - { - _logger.LogDebug("正在获取蜂窝网络状态: {InterfaceName}", interfaceName); - var result = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); - - if (!result.IsSuccess) - { - _logger.LogError("获取蜂窝网络状态失败: {Error}", result.Error); - return NetworkStatus.Unknown; - } - - var output = result.Output; - if (output.Contains("已连接", StringComparison.OrdinalIgnoreCase)) - { - return NetworkStatus.Connected; - } - else if (output.Contains("已断开", StringComparison.OrdinalIgnoreCase)) - { - return NetworkStatus.Disconnected; - } - - return NetworkStatus.Unknown; - } - catch (Exception ex) - { - _logger.LogError(ex, "获取蜂窝网络状态失败: {InterfaceName}", interfaceName); - return NetworkStatus.Unknown; - } - } - - public async Task GetSignalStrengthAsync(string interfaceName) - { - try - { - _logger.LogDebug("正在获取蜂窝网络信号强度: {InterfaceName}", interfaceName); - var result = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); - - if (!result.IsSuccess) - { - _logger.LogError("获取蜂窝网络信号强度失败: {Error}", result.Error); - return SignalStrength.NoSignal; - } - - var output = result.Output; - if (output.Contains("信号强度: 强", StringComparison.OrdinalIgnoreCase)) - { - return SignalStrength.Strong; - } - else if (output.Contains("信号强度: 中", StringComparison.OrdinalIgnoreCase)) - { - return SignalStrength.Medium; - } - else if (output.Contains("信号强度: 弱", StringComparison.OrdinalIgnoreCase)) - { - return SignalStrength.Weak; - } - - return SignalStrength.NoSignal; - } - catch (Exception ex) - { - _logger.LogError(ex, "获取蜂窝网络信号强度失败: {InterfaceName}", interfaceName); - return SignalStrength.NoSignal; - } - } - - public async Task GetNetworkTypeAsync(string interfaceName) - { - try - { - _logger.LogDebug("正在获取蜂窝网络类型: {InterfaceName}", interfaceName); - var result = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); - - if (!result.IsSuccess) - { - _logger.LogError("获取蜂窝网络类型失败: {Error}", result.Error); - return NetworkType.Unknown; - } - - var output = result.Output; - if (output.Contains("5G", StringComparison.OrdinalIgnoreCase)) - { - return NetworkType.G5; - } - else if (output.Contains("4G", StringComparison.OrdinalIgnoreCase)) - { - return NetworkType.G4; - } - else if (output.Contains("3G", StringComparison.OrdinalIgnoreCase)) - { - return NetworkType.G3; - } - else if (output.Contains("2G", StringComparison.OrdinalIgnoreCase)) - { - return NetworkType.G2; - } - - return NetworkType.Unknown; - } - catch (Exception ex) - { - _logger.LogError(ex, "获取蜂窝网络类型失败: {InterfaceName}", interfaceName); - return NetworkType.Unknown; - } - } - - public async Task SetTransmitPowerAsync(string interfaceName, int powerLevel) - { - try - { - if (!_globalStatus.IsInitialized) - { - _logger.LogWarning("蜂窝网络未初始化,无法设置发射功率"); - return false; - } - - if (powerLevel < 0 || powerLevel > 100) - { - _logger.LogWarning("发射功率设置无效: {PowerLevel}", powerLevel); - return false; - } - - _logger.LogInformation("正在设置蜂窝网络发射功率: {InterfaceName}, {PowerLevel}", interfaceName, powerLevel); - - // 设置发射功率 - var result = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" power={powerLevel}"); - if (!result) - { - _logger.LogError("设置蜂窝网络发射功率失败"); - return false; - } - - _globalStatus.CurrentTransmitPower = powerLevel; - _logger.LogInformation("蜂窝网络发射功率设置成功: {PowerLevel}", powerLevel); - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "设置蜂窝网络发射功率失败: {InterfaceName}, {PowerLevel}", interfaceName, powerLevel); - return false; - } - } - - public Task GetGlobalStatusAsync() - { - return Task.FromResult(_globalStatus); - } - - private async Task ConfigureNetworkAsync(string interfaceName, CellularNetworkConfig config) - { - try - { - _logger.LogDebug("正在配置蜂窝网络参数: {InterfaceName}", interfaceName); - - // 配置APN - var apnResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" apn=\"{config.Apn}\""); - if (!apnResult) - { - return false; - } - - // 配置用户名和密码 - if (!string.IsNullOrEmpty(config.Username) && !string.IsNullOrEmpty(config.Password)) - { - var authResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" username=\"{config.Username}\" password=\"{config.Password}\""); - if (!authResult) - { - return false; - } - } - - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "配置蜂窝网络参数失败: {InterfaceName}", interfaceName); - return false; - } - } - - private async Task WaitForConnectionAsync(string interfaceName) - { - const int maxAttempts = 30; - const int delayMs = 1000; - - for (int i = 0; i < maxAttempts; i++) - { - var status = await GetNetworkStatusAsync(interfaceName); - if (status == NetworkStatus.Connected) - { - return true; - } - - await Task.Delay(delayMs); - } - - return false; - } - - private async Task ExecuteCommandAsync(string command) - { - try - { - var executor = _commandExecutorFactory.CreateExecutor(); - using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - var result = await executor.ExecuteCommandAsync(command, cts); - - if (!result.IsSuccess) - { - _logger.LogError("命令执行失败: {Command}, 错误: {Error}", command, result.Error); - return false; - } - - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "执行命令失败: {Command}", command); - return false; - } - } - - private async Task ExecuteCommandWithResultAsync(string command) - { - try - { - var executor = _commandExecutorFactory.CreateExecutor(); - using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - return await executor.ExecuteCommandAsync(command, cts); - } - catch (Exception ex) - { - _logger.LogError(ex, "执行命令失败: {Command}", command); - return CommandExecutionResult.Failure(ex.Message, 0); - } - } -} \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/Configuration/NetworkCommandConfigurationService.cs b/CoreAgent.Infrastructure/Services/Configuration/NetworkCommandConfigurationService.cs new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/CoreAgent.Infrastructure/Services/Configuration/NetworkCommandConfigurationService.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/Network/CellularNetworkConfigurator.cs b/CoreAgent.Infrastructure/Services/Network/CellularNetworkConfigurator.cs new file mode 100644 index 0000000..f9bb384 --- /dev/null +++ b/CoreAgent.Infrastructure/Services/Network/CellularNetworkConfigurator.cs @@ -0,0 +1,110 @@ +using CoreAgent.Domain.Interfaces.Network; +using CoreAgent.Domain.Interfaces.System.Command; +using CoreAgent.Domain.Models.Network; +using Microsoft.Extensions.Logging; + +namespace CoreAgent.Infrastructure.Services.Network; + +/// +/// 蜂窝网络配置器实现 +/// +public class CellularNetworkConfigurator : INetworkConfigurator +{ + private readonly ILogger _logger; + private readonly ISystemCommandExecutor _commandExecutor; + + public CellularNetworkConfigurator( + ILogger logger, + ISystemCommandExecutor commandExecutor) + { + _logger = logger; + _commandExecutor = commandExecutor; + } + + public async Task ConfigureAsync(string interfaceName, CellularNetworkConfig config) + { + try + { + _logger.LogInformation("正在配置蜂窝网络接口: {InterfaceName}", interfaceName); + + // 1. 配置APN + if (!string.IsNullOrEmpty(config.Apn)) + { + var apnResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" apn=\"{config.Apn}\""); + if (!apnResult) + { + _logger.LogError("配置APN失败"); + return false; + } + } + + // 2. 配置认证信息 + if (!string.IsNullOrEmpty(config.Username) && !string.IsNullOrEmpty(config.Password)) + { + var authResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" username=\"{config.Username}\" password=\"{config.Password}\""); + if (!authResult) + { + _logger.LogError("配置认证信息失败"); + return false; + } + } + + // 3. 配置网络类型 + //if (config.NetworkType != NetworkType.Auto) + //{ + // var networkTypeResult = await ExecuteCommandAsync( + // $"netsh interface cellular set networktype \"{interfaceName}\" " + + // $"type={(int)config.NetworkType}"); + // if (!networkTypeResult) + // { + // _logger.LogError("配置网络类型失败"); + // return false; + // } + //} + + _logger.LogInformation("蜂窝网络接口 {InterfaceName} 配置成功", interfaceName); + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "配置蜂窝网络接口 {InterfaceName} 失败", interfaceName); + return false; + } + } + + public async Task SetTransmitPowerAsync(string interfaceName, int powerLevel) + { + try + { + if (powerLevel < 0 || powerLevel > 100) + { + _logger.LogWarning("发射功率设置无效: {PowerLevel}", powerLevel); + return false; + } + + _logger.LogInformation("正在设置蜂窝网络发射功率: {InterfaceName}, {PowerLevel}", interfaceName, powerLevel); + + // 设置发射功率 + var result = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" power={powerLevel}"); + if (!result) + { + _logger.LogError("设置蜂窝网络发射功率失败"); + return false; + } + + _logger.LogInformation("蜂窝网络发射功率设置成功: {PowerLevel}", powerLevel); + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "设置蜂窝网络发射功率失败: {InterfaceName}, {PowerLevel}", interfaceName, powerLevel); + return false; + } + } + + private async Task ExecuteCommandAsync(string command) + { + var result = await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource()); + return result.IsSuccess; + } +} \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs b/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs new file mode 100644 index 0000000..605ceb8 --- /dev/null +++ b/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs @@ -0,0 +1,162 @@ +using CoreAgent.Domain.Contexts; +using CoreAgent.Domain.Interfaces.Network; +using CoreAgent.Domain.Interfaces.System.Command; +using CoreAgent.Domain.Models.Network; +using CoreAgent.Domain.Models.System; +using Microsoft.Extensions.Logging; + +namespace CoreAgent.Infrastructure.Services.Network; + +/// +/// 蜂窝网络服务实现 +/// +public class CellularNetworkService : ICellularNetworkService +{ + private readonly ILogger _logger; + private readonly ISystemCommandExecutor _commandExecutor; + private readonly INetworkConfigurator _configurator; + private readonly CellularNetworkContext _context; + private static readonly SemaphoreSlim _startLock = new(1, 1); + + public CellularNetworkService( + ILogger logger, + ISystemCommandExecutor commandExecutor, + INetworkConfigurator configurator) + { + _logger = logger; + _commandExecutor = commandExecutor; + _configurator = configurator; + _context = CellularNetworkContext.Instance; + } + + public async Task StartAsync(string interfaceName, CellularNetworkConfig config) + { + try + { + // 使用信号量确保只能启动一次 + if (!await _startLock.WaitAsync(TimeSpan.FromSeconds(5))) + { + _logger.LogWarning("蜂窝网络启动操作被锁定,可能已有其他启动操作正在进行"); + return false; + } + + try + { + var commands = _context.GetNetworkCommandConfig(); + + var state = _context.GetOrCreateNetworkState(interfaceName); + if (state.IsInitialized) + { + _logger.LogWarning("蜂窝网络已经初始化,不能重复启动"); + return false; + } + + _logger.LogInformation("正在启动蜂窝网络接口: {InterfaceName}", interfaceName); + + // 1. 配置网络参数 + var configResult = await _configurator.ConfigureAsync(interfaceName, config); + if (!configResult) + { + _logger.LogError("配置蜂窝网络参数失败"); + return false; + } + + // 2. 启动网络接口 + var startResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" admin=enable"); + if (!startResult) + { + _logger.LogError("启动蜂窝网络接口失败"); + return false; + } + + // 3. 等待网络连接 + var connected = await WaitForConnectionAsync(interfaceName); + if (!connected) + { + _logger.LogError("蜂窝网络连接超时"); + return false; + } + + // 4. 更新状态 + state.UpdateConfig(config); + state.MarkAsStarted(); + + _logger.LogInformation("蜂窝网络接口 {InterfaceName} 启动成功", interfaceName); + return true; + } + finally + { + _startLock.Release(); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "启动蜂窝网络接口 {InterfaceName} 失败", interfaceName); + return false; + } + } + + public async Task StopAsync(string interfaceName) + { + try + { + var state = _context.GetOrCreateNetworkState(interfaceName); + if (!state.IsInitialized) + { + _logger.LogWarning("蜂窝网络未初始化,无需停止"); + return true; + } + + _logger.LogInformation("正在停止蜂窝网络接口: {InterfaceName}", interfaceName); + + // 1. 停止网络接口 + var stopResult = await ExecuteCommandAsync($"netsh interface cellular set interface \"{interfaceName}\" admin=disable"); + if (!stopResult) + { + _logger.LogError("停止蜂窝网络接口失败"); + return false; + } + + // 2. 更新状态 + state.MarkAsStopped(); + + _logger.LogInformation("蜂窝网络接口 {InterfaceName} 停止成功", interfaceName); + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "停止蜂窝网络接口 {InterfaceName} 失败", interfaceName); + return false; + } + } + + private async Task WaitForConnectionAsync(string interfaceName) + { + const int maxAttempts = 30; + const int delayMs = 1000; + + for (int i = 0; i < maxAttempts; i++) + { + var status = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); + if (status.IsSuccess && status.Output.Contains("已连接", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + await Task.Delay(delayMs); + } + + return false; + } + + private async Task ExecuteCommandAsync(string command) + { + var result = await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource()); + return result.IsSuccess; + } + + private async Task ExecuteCommandWithResultAsync(string command) + { + return await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource()); + } +} \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/Network/CellularNetworkStatusProvider.cs b/CoreAgent.Infrastructure/Services/Network/CellularNetworkStatusProvider.cs new file mode 100644 index 0000000..fe01a5e --- /dev/null +++ b/CoreAgent.Infrastructure/Services/Network/CellularNetworkStatusProvider.cs @@ -0,0 +1,244 @@ +using CoreAgent.Domain.Contexts; +using CoreAgent.Domain.Interfaces.Network; +using CoreAgent.Domain.Interfaces.System.Command; +using CoreAgent.Domain.Models.Network; +using CoreAgent.Domain.Models.System; +using Microsoft.Extensions.Logging; + +namespace CoreAgent.Infrastructure.Services.Network; + +/// +/// 蜂窝网络状态提供者实现 +/// +public class CellularNetworkStatusProvider : INetworkStatusProvider +{ + private readonly ILogger _logger; + private readonly ISystemCommandExecutor _commandExecutor; + private readonly CellularNetworkContext _context; + + public CellularNetworkStatusProvider( + ILogger logger, + ISystemCommandExecutor commandExecutor) + { + _logger = logger; + _commandExecutor = commandExecutor; + _context = CellularNetworkContext.Instance; + } + + public async Task GetNetworkStatusAsync(string interfaceName) + { + try + { + var result = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); + if (!result.IsSuccess) + { + _logger.LogError("获取蜂窝网络状态失败"); + return NetworkStatus.Unknown; + } + + var state = _context.GetOrCreateNetworkState(interfaceName); + var status = ParseNetworkStatus(result.Output); + state.UpdateStatus(status); + return status; + } + catch (Exception ex) + { + _logger.LogError(ex, "获取蜂窝网络状态失败"); + return NetworkStatus.Unknown; + } + } + + public async Task GetSignalStrengthAsync(string interfaceName) + { + try + { + var result = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); + if (!result.IsSuccess) + { + _logger.LogError("获取蜂窝网络信号强度失败"); + return SignalStrength.NoSignal; + } + + var state = _context.GetOrCreateNetworkState(interfaceName); + var strength = ParseSignalStrength(result.Output); + state.UpdateSignalStrength(strength); + return strength; + } + catch (Exception ex) + { + _logger.LogError(ex, "获取蜂窝网络信号强度失败"); + return SignalStrength.NoSignal; + } + } + + public async Task GetNetworkTypeAsync(string interfaceName) + { + try + { + var result = await ExecuteCommandWithResultAsync($"netsh interface cellular show interfaces \"{interfaceName}\""); + if (!result.IsSuccess) + { + _logger.LogError("获取蜂窝网络类型失败"); + return NetworkType.Unknown; + } + + var state = _context.GetOrCreateNetworkState(interfaceName); + var type = ParseNetworkType(result.Output); + state.UpdateNetworkType(type); + return type; + } + catch (Exception ex) + { + _logger.LogError(ex, "获取蜂窝网络类型失败"); + return NetworkType.Unknown; + } + } + + public async Task GetGlobalStatusAsync() + { + try + { + var result = await ExecuteCommandWithResultAsync("netsh interface cellular show interfaces"); + if (!result.IsSuccess) + { + _logger.LogError("获取蜂窝网络全局状态失败"); + return new CellularNetworkGlobalStatus + { + IsInitialized = false, + CurrentStatus = NetworkStatus.Unknown, + CurrentSignalStrength = SignalStrength.NoSignal, + CurrentNetworkType = NetworkType.Unknown, + CurrentTransmitPower = 0 + }; + } + + // 解析所有接口的状态 + var interfaces = ParseInterfaces(result.Output); + foreach (var iface in interfaces) + { + var state = _context.GetOrCreateNetworkState(iface.Name); + state.UpdateStatus(iface.Status); + state.UpdateSignalStrength(iface.SignalStrength); + state.UpdateNetworkType(iface.NetworkType); + } + + // 聚合所有接口的状态 + var states = _context.GetAllNetworkStates(); + return new CellularNetworkGlobalStatus + { + IsInitialized = states.Any(s => s.IsInitialized), + LastStartTime = states.Max(s => s.LastStartTime), + LastStopTime = states.Max(s => s.LastStopTime), + CurrentStatus = states.FirstOrDefault()?.CurrentStatus ?? NetworkStatus.Unknown, + CurrentSignalStrength = states.FirstOrDefault()?.CurrentSignalStrength ?? SignalStrength.NoSignal, + CurrentNetworkType = states.FirstOrDefault()?.CurrentNetworkType ?? NetworkType.Unknown, + CurrentTransmitPower = states.FirstOrDefault()?.CurrentTransmitPower ?? 0 + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "获取蜂窝网络全局状态失败"); + return new CellularNetworkGlobalStatus + { + IsInitialized = false, + CurrentStatus = NetworkStatus.Unknown, + CurrentSignalStrength = SignalStrength.NoSignal, + CurrentNetworkType = NetworkType.Unknown, + CurrentTransmitPower = 0 + }; + } + } + + private async Task ExecuteCommandWithResultAsync(string command) + { + return await _commandExecutor.ExecuteCommandAsync(command, new CancellationTokenSource()); + } + + private NetworkStatus ParseNetworkStatus(string output) + { + if (output.Contains("已连接", StringComparison.OrdinalIgnoreCase)) + return NetworkStatus.Connected; + if (output.Contains("已断开", StringComparison.OrdinalIgnoreCase)) + return NetworkStatus.Disconnected; + return NetworkStatus.Unknown; + } + + private SignalStrength ParseSignalStrength(string output) + { + if (output.Contains("信号强度: 强", StringComparison.OrdinalIgnoreCase)) + return SignalStrength.Strong; + if (output.Contains("信号强度: 中", StringComparison.OrdinalIgnoreCase)) + return SignalStrength.Medium; + if (output.Contains("信号强度: 弱", StringComparison.OrdinalIgnoreCase)) + return SignalStrength.Weak; + return SignalStrength.NoSignal; + } + + private NetworkType ParseNetworkType(string output) + { + if (output.Contains("5G", StringComparison.OrdinalIgnoreCase)) + return NetworkType.G5; + if (output.Contains("4G", StringComparison.OrdinalIgnoreCase)) + return NetworkType.G4; + if (output.Contains("3G", StringComparison.OrdinalIgnoreCase)) + return NetworkType.G3; + if (output.Contains("2G", StringComparison.OrdinalIgnoreCase)) + return NetworkType.G2; + return NetworkType.Unknown; + } + + private class InterfaceInfo + { + public string Name { get; set; } + public NetworkStatus Status { get; set; } + public SignalStrength SignalStrength { get; set; } + public NetworkType NetworkType { get; set; } + } + + private IEnumerable ParseInterfaces(string output) + { + var interfaces = new List(); + var lines = output.Split('\n'); + InterfaceInfo currentInterface = null; + + foreach (var line in lines) + { + if (line.Contains("接口名称:", StringComparison.OrdinalIgnoreCase)) + { + if (currentInterface != null) + { + interfaces.Add(currentInterface); + } + currentInterface = new InterfaceInfo + { + Name = line.Split(':')[1].Trim(), + Status = NetworkStatus.Unknown, + SignalStrength = SignalStrength.NoSignal, + NetworkType = NetworkType.Unknown + }; + } + else if (currentInterface != null) + { + if (line.Contains("状态:", StringComparison.OrdinalIgnoreCase)) + { + currentInterface.Status = ParseNetworkStatus(line); + } + else if (line.Contains("信号强度:", StringComparison.OrdinalIgnoreCase)) + { + currentInterface.SignalStrength = ParseSignalStrength(line); + } + else if (line.Contains("网络类型:", StringComparison.OrdinalIgnoreCase)) + { + currentInterface.NetworkType = ParseNetworkType(line); + } + } + } + + if (currentInterface != null) + { + interfaces.Add(currentInterface); + } + + return interfaces; + } +} \ No newline at end of file