using AmtScanner.Api.Data; using AmtScanner.Api.Models; using AmtScanner.Api.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace AmtScanner.Api.Controllers; [ApiController] [Route("api/[controller]")] public class PowerController : ControllerBase { private readonly AppDbContext _context; private readonly IAmtPowerService _powerService; private readonly ICredentialService _credentialService; private readonly ILogger _logger; public PowerController( AppDbContext context, IAmtPowerService powerService, ICredentialService credentialService, ILogger logger) { _context = context; _powerService = powerService; _credentialService = credentialService; _logger = logger; } /// /// 获取设备电源状态 /// [HttpGet("{deviceId}/state")] public async Task>> GetPowerState(long deviceId) { var device = await _context.AmtDevices.FindAsync(deviceId); if (device == null) { return Ok(ApiResponse.Fail(404, "设备不存在")); } var credential = await _credentialService.GetDefaultCredentialAsync(); if (credential == null) { return Ok(ApiResponse.Fail(400, "没有配置默认凭据")); } var openPorts = new List(); if (device.AmtOnline) { // 检测可用端口 openPorts = await DetectOpenPortsAsync(device.IpAddress); } if (openPorts.Count == 0) { return Ok(ApiResponse.Success(new PowerStateResponse { DeviceId = deviceId, IpAddress = device.IpAddress, Success = false, Error = "设备离线或AMT端口不可用" })); } // 解密密码 var decryptedPassword = _credentialService.DecryptPassword(credential.Password); var result = await _powerService.GetPowerStateAsync( device.IpAddress, credential.Username, decryptedPassword, openPorts); return Ok(ApiResponse.Success(new PowerStateResponse { DeviceId = deviceId, IpAddress = device.IpAddress, Success = result.Success, PowerState = result.PowerState, PowerStateText = result.PowerStateText, Error = result.Error })); } /// /// 开机 /// [HttpPost("{deviceId}/power-on")] public async Task>> PowerOn(long deviceId) { return await ExecutePowerAction(deviceId, PowerAction.PowerOn); } /// /// 关机(优雅关机) /// [HttpPost("{deviceId}/power-off")] public async Task>> PowerOff(long deviceId) { return await ExecutePowerAction(deviceId, PowerAction.GracefulOff); } /// /// 强制关机 /// [HttpPost("{deviceId}/force-off")] public async Task>> ForceOff(long deviceId) { return await ExecutePowerAction(deviceId, PowerAction.PowerOff); } /// /// 重启(优雅重启) /// [HttpPost("{deviceId}/restart")] public async Task>> Restart(long deviceId) { return await ExecutePowerAction(deviceId, PowerAction.GracefulReset); } /// /// 强制重启 /// [HttpPost("{deviceId}/force-restart")] public async Task>> ForceRestart(long deviceId) { return await ExecutePowerAction(deviceId, PowerAction.Reset); } /// /// 电源循环(硬重启) /// [HttpPost("{deviceId}/power-cycle")] public async Task>> PowerCycle(long deviceId) { return await ExecutePowerAction(deviceId, PowerAction.PowerCycle); } private async Task>> ExecutePowerAction(long deviceId, PowerAction action) { var device = await _context.AmtDevices.FindAsync(deviceId); if (device == null) { return Ok(ApiResponse.Fail(404, "设备不存在")); } var credential = await _credentialService.GetDefaultCredentialAsync(); if (credential == null) { return Ok(ApiResponse.Fail(400, "没有配置默认凭据")); } // 检测可用端口 var openPorts = await DetectOpenPortsAsync(device.IpAddress); if (openPorts.Count == 0) { return Ok(ApiResponse.Success(new PowerActionResponse { DeviceId = deviceId, IpAddress = device.IpAddress, Action = action.ToString(), Success = false, Error = "AMT端口不可用" })); } // 解密密码 var decryptedPassword = _credentialService.DecryptPassword(credential.Password); var result = await _powerService.ChangePowerStateAsync( device.IpAddress, credential.Username, decryptedPassword, openPorts, action); return Ok(ApiResponse.Success(new PowerActionResponse { DeviceId = deviceId, IpAddress = device.IpAddress, Action = action.ToString(), Success = result.Success, Message = result.Message, Error = result.Error })); } private async Task> DetectOpenPortsAsync(string ipAddress) { var openPorts = new List(); int[] amtPorts = { 16992, 16993 }; foreach (var port in amtPorts) { try { using var client = new System.Net.Sockets.TcpClient(); var connectTask = client.ConnectAsync(ipAddress, port); if (await Task.WhenAny(connectTask, Task.Delay(1000)) == connectTask) { if (client.Connected) { openPorts.Add(port); } } } catch { // 端口不可用 } } return openPorts; } } public class PowerStateResponse { public long DeviceId { get; set; } public string IpAddress { get; set; } = string.Empty; public bool Success { get; set; } public int PowerState { get; set; } public string PowerStateText { get; set; } = string.Empty; public string? Error { get; set; } } public class PowerActionResponse { public long DeviceId { get; set; } public string IpAddress { get; set; } = string.Empty; public string Action { get; set; } = string.Empty; public bool Success { get; set; } public string Message { get; set; } = string.Empty; public string? Error { get; set; } }