220 lines
7.0 KiB
C#

using AmtScanner.Api.Data;
using AmtScanner.Api.Models;
using AmtScanner.Api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace AmtScanner.Api.Controllers;
[ApiController]
[Route("api/amt-power")]
[Authorize]
public class AmtPowerController : ControllerBase
{
private readonly AppDbContext _db;
private readonly IAmtPowerService _powerService;
private readonly ILogger<AmtPowerController> _logger;
public AmtPowerController(AppDbContext db, IAmtPowerService powerService, ILogger<AmtPowerController> logger)
{
_db = db;
_powerService = powerService;
_logger = logger;
}
/// <summary>
/// 获取设备电源状态
/// </summary>
[HttpGet("{uuid}/state")]
public async Task<IActionResult> GetPowerState(string uuid)
{
var device = await _db.AmtDevices_new.FindAsync(uuid);
if (device == null)
{
return NotFound(ApiResponse<object>.Fail(404, "设备不存在"));
}
if (string.IsNullOrEmpty(device.AmtUsername) || string.IsNullOrEmpty(device.AmtPassword))
{
return BadRequest(ApiResponse<object>.Fail(400, "设备未配置 AMT 凭据"));
}
try
{
var state = await _powerService.GetPowerStateAsync(
device.IpAddress, device.AmtUsername, device.AmtPassword);
if (state == null)
{
// 返回离线状态而不是错误
return Ok(ApiResponse<object>.Success(new {
powerState = 0,
powerStateText = $"AMT离线({device.IpAddress})"
}));
}
return Ok(ApiResponse<object>.Success(state));
}
catch (Exception ex)
{
_logger.LogError(ex, "获取电源状态失败: {Uuid}", uuid);
// 返回离线状态而不是错误
return Ok(ApiResponse<object>.Success(new {
powerState = 0,
powerStateText = $"AMT离线({device.IpAddress})"
}));
}
}
/// <summary>
/// 测试 AMT 连接(用于诊断)
/// </summary>
[HttpGet("{uuid}/test-connection")]
public async Task<IActionResult> TestConnection(string uuid)
{
var device = await _db.AmtDevices_new.FindAsync(uuid);
if (device == null)
{
return NotFound(ApiResponse<object>.Fail(404, "设备不存在"));
}
if (string.IsNullOrEmpty(device.AmtUsername) || string.IsNullOrEmpty(device.AmtPassword))
{
return BadRequest(ApiResponse<object>.Fail(400, "设备未配置 AMT 凭据"));
}
var result = new
{
uuid = device.Uuid,
ipAddress = device.IpAddress,
amtPort16992 = await TestPortAsync(device.IpAddress, 16992),
amtPort16993 = await TestPortAsync(device.IpAddress, 16993),
pingable = await TestPingAsync(device.IpAddress)
};
return Ok(ApiResponse<object>.Success(result));
}
private async Task<bool> TestPortAsync(string ip, int port)
{
try
{
using var client = new System.Net.Sockets.TcpClient();
var connectTask = client.ConnectAsync(ip, port);
var timeoutTask = Task.Delay(2000);
var completedTask = await Task.WhenAny(connectTask, timeoutTask);
return completedTask == connectTask && client.Connected;
}
catch
{
return false;
}
}
private async Task<bool> TestPingAsync(string ip)
{
try
{
using var ping = new System.Net.NetworkInformation.Ping();
var reply = await ping.SendPingAsync(ip, 2000);
return reply.Status == System.Net.NetworkInformation.IPStatus.Success;
}
catch
{
return false;
}
}
/// <summary>
/// 开机
/// </summary>
[HttpPost("{uuid}/power-on")]
public async Task<IActionResult> PowerOn(string uuid)
{
return await ExecutePowerAction(uuid, "power-on", async (ip, user, pwd) =>
await _powerService.PowerOnAsync(ip, user, pwd), "开机");
}
/// <summary>
/// 关机
/// </summary>
[HttpPost("{uuid}/power-off")]
public async Task<IActionResult> PowerOff(string uuid)
{
return await ExecutePowerAction(uuid, "power-off", async (ip, user, pwd) =>
await _powerService.PowerOffAsync(ip, user, pwd), "关机");
}
/// <summary>
/// 重启
/// </summary>
[HttpPost("{uuid}/reset")]
public async Task<IActionResult> Reset(string uuid)
{
return await ExecutePowerAction(uuid, "reset", async (ip, user, pwd) =>
await _powerService.ResetAsync(ip, user, pwd), "重启");
}
/// <summary>
/// 电源循环
/// </summary>
[HttpPost("{uuid}/power-cycle")]
public async Task<IActionResult> PowerCycle(string uuid)
{
return await ExecutePowerAction(uuid, "power-cycle", async (ip, user, pwd) =>
await _powerService.PowerCycleAsync(ip, user, pwd), "电源循环");
}
/// <summary>
/// 强制关机(硬关机)
/// </summary>
[HttpPost("{uuid}/hard-power-off")]
public async Task<IActionResult> HardPowerOff(string uuid)
{
return await ExecutePowerAction(uuid, "hard-power-off", async (ip, user, pwd) =>
await _powerService.HardPowerOffAsync(ip, user, pwd), "强制关机");
}
/// <summary>
/// 强制重启(硬重启)
/// </summary>
[HttpPost("{uuid}/hard-reset")]
public async Task<IActionResult> HardReset(string uuid)
{
return await ExecutePowerAction(uuid, "hard-reset", async (ip, user, pwd) =>
await _powerService.HardResetAsync(ip, user, pwd), "强制重启");
}
private async Task<IActionResult> ExecutePowerAction(string uuid, string action,
Func<string, string, string, Task<bool>> powerAction, string actionName)
{
var device = await _db.AmtDevices_new.FindAsync(uuid);
if (device == null)
{
return NotFound(ApiResponse<object>.Fail(404, "设备不存在"));
}
if (string.IsNullOrEmpty(device.AmtUsername) || string.IsNullOrEmpty(device.AmtPassword))
{
return BadRequest(ApiResponse<object>.Fail(400, "设备未配置 AMT 凭据"));
}
try
{
var success = await powerAction(device.IpAddress, device.AmtUsername, device.AmtPassword);
if (!success)
{
return BadRequest(ApiResponse<object>.Fail(400, $"{actionName}失败"));
}
return Ok(ApiResponse<object>.Success(null, $"{actionName}成功"));
}
catch (Exception ex)
{
_logger.LogError(ex, "{Action}失败: {Uuid}", actionName, uuid);
return BadRequest(ApiResponse<object>.Fail(400, $"{actionName}失败: {ex.Message}"));
}
}
}