239 lines
7.3 KiB
C#

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<PowerController> _logger;
public PowerController(
AppDbContext context,
IAmtPowerService powerService,
ICredentialService credentialService,
ILogger<PowerController> logger)
{
_context = context;
_powerService = powerService;
_credentialService = credentialService;
_logger = logger;
}
/// <summary>
/// 获取设备电源状态
/// </summary>
[HttpGet("{deviceId}/state")]
public async Task<ActionResult<ApiResponse<PowerStateResponse>>> GetPowerState(long deviceId)
{
var device = await _context.AmtDevices.FindAsync(deviceId);
if (device == null)
{
return Ok(ApiResponse<PowerStateResponse>.Fail(404, "设备不存在"));
}
var credential = await _credentialService.GetDefaultCredentialAsync();
if (credential == null)
{
return Ok(ApiResponse<PowerStateResponse>.Fail(400, "没有配置默认凭据"));
}
var openPorts = new List<int>();
if (device.AmtOnline)
{
// 检测可用端口
openPorts = await DetectOpenPortsAsync(device.IpAddress);
}
if (openPorts.Count == 0)
{
return Ok(ApiResponse<PowerStateResponse>.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<PowerStateResponse>.Success(new PowerStateResponse
{
DeviceId = deviceId,
IpAddress = device.IpAddress,
Success = result.Success,
PowerState = result.PowerState,
PowerStateText = result.PowerStateText,
Error = result.Error
}));
}
/// <summary>
/// 开机
/// </summary>
[HttpPost("{deviceId}/power-on")]
public async Task<ActionResult<ApiResponse<PowerActionResponse>>> PowerOn(long deviceId)
{
return await ExecutePowerAction(deviceId, PowerAction.PowerOn);
}
/// <summary>
/// 关机(优雅关机)
/// </summary>
[HttpPost("{deviceId}/power-off")]
public async Task<ActionResult<ApiResponse<PowerActionResponse>>> PowerOff(long deviceId)
{
return await ExecutePowerAction(deviceId, PowerAction.GracefulOff);
}
/// <summary>
/// 强制关机
/// </summary>
[HttpPost("{deviceId}/force-off")]
public async Task<ActionResult<ApiResponse<PowerActionResponse>>> ForceOff(long deviceId)
{
return await ExecutePowerAction(deviceId, PowerAction.PowerOff);
}
/// <summary>
/// 重启(优雅重启)
/// </summary>
[HttpPost("{deviceId}/restart")]
public async Task<ActionResult<ApiResponse<PowerActionResponse>>> Restart(long deviceId)
{
return await ExecutePowerAction(deviceId, PowerAction.GracefulReset);
}
/// <summary>
/// 强制重启
/// </summary>
[HttpPost("{deviceId}/force-restart")]
public async Task<ActionResult<ApiResponse<PowerActionResponse>>> ForceRestart(long deviceId)
{
return await ExecutePowerAction(deviceId, PowerAction.Reset);
}
/// <summary>
/// 电源循环(硬重启)
/// </summary>
[HttpPost("{deviceId}/power-cycle")]
public async Task<ActionResult<ApiResponse<PowerActionResponse>>> PowerCycle(long deviceId)
{
return await ExecutePowerAction(deviceId, PowerAction.PowerCycle);
}
private async Task<ActionResult<ApiResponse<PowerActionResponse>>> ExecutePowerAction(long deviceId, PowerAction action)
{
var device = await _context.AmtDevices.FindAsync(deviceId);
if (device == null)
{
return Ok(ApiResponse<PowerActionResponse>.Fail(404, "设备不存在"));
}
var credential = await _credentialService.GetDefaultCredentialAsync();
if (credential == null)
{
return Ok(ApiResponse<PowerActionResponse>.Fail(400, "没有配置默认凭据"));
}
// 检测可用端口
var openPorts = await DetectOpenPortsAsync(device.IpAddress);
if (openPorts.Count == 0)
{
return Ok(ApiResponse<PowerActionResponse>.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<PowerActionResponse>.Success(new PowerActionResponse
{
DeviceId = deviceId,
IpAddress = device.IpAddress,
Action = action.ToString(),
Success = result.Success,
Message = result.Message,
Error = result.Error
}));
}
private async Task<List<int>> DetectOpenPortsAsync(string ipAddress)
{
var openPorts = new List<int>();
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; }
}