220 lines
7.0 KiB
C#
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}"));
|
|
}
|
|
}
|
|
}
|