using AmtScanner.Api.Data; using AmtScanner.Api.Models; using AmtScanner.Api.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.Net.Sockets; namespace AmtScanner.Api.Controllers; [ApiController] [Route("api/[controller]")] public class DevicesController : ControllerBase { private readonly AppDbContext _context; private readonly ILogger _logger; private readonly IAmtPowerService _powerService; private readonly ICredentialService _credentialService; public DevicesController( AppDbContext context, ILogger logger, IAmtPowerService powerService, ICredentialService credentialService) { _context = context; _logger = logger; _powerService = powerService; _credentialService = credentialService; } [HttpGet] public async Task>> GetAllDevices() { return await _context.AmtDevices.ToListAsync(); } [HttpGet("{id}")] public async Task> GetDevice(long id) { var device = await _context.AmtDevices.FindAsync(id); if (device == null) { return NotFound(); } return device; } [HttpDelete("{id}")] public async Task DeleteDevice(long id) { var device = await _context.AmtDevices.FindAsync(id); if (device == null) { return NotFound(); } _context.AmtDevices.Remove(device); await _context.SaveChangesAsync(); return NoContent(); } /// /// 检测所有设备的在线状态 /// [HttpGet("status")] public async Task>> CheckAllDevicesStatus() { var devices = await _context.AmtDevices.ToListAsync(); var credentials = await _context.AmtCredentials.ToListAsync(); var statusList = new List(); // 并行检测所有设备 var tasks = devices.Select(async device => { var (amtOnline, openPorts) = await CheckAmtOnlineAsync(device.IpAddress); var osOnline = false; // 如果 AMT 在线,尝试查询电源状态来判断 OS 是否在线 if (amtOnline && openPorts.Count > 0) { osOnline = await CheckOsOnlineAsync(device.IpAddress, openPorts, credentials); } // 更新数据库中的在线状态 device.AmtOnline = amtOnline; device.OsOnline = osOnline; if (amtOnline) { device.LastSeenAt = DateTime.UtcNow; } return new DeviceStatusDto { Id = device.Id, IpAddress = device.IpAddress, AmtOnline = amtOnline, OsOnline = osOnline }; }); statusList = (await Task.WhenAll(tasks)).ToList(); // 保存更新 await _context.SaveChangesAsync(); return statusList; } /// /// 检测单个设备的在线状态 /// [HttpGet("{id}/status")] public async Task> CheckDeviceStatus(long id) { var device = await _context.AmtDevices.FindAsync(id); if (device == null) { return NotFound(); } var credentials = await _context.AmtCredentials.ToListAsync(); var (amtOnline, openPorts) = await CheckAmtOnlineAsync(device.IpAddress); var osOnline = false; // 如果 AMT 在线,尝试查询电源状态来判断 OS 是否在线 if (amtOnline && openPorts.Count > 0) { osOnline = await CheckOsOnlineAsync(device.IpAddress, openPorts, credentials); } // 更新数据库 device.AmtOnline = amtOnline; device.OsOnline = osOnline; if (amtOnline) { device.LastSeenAt = DateTime.UtcNow; } await _context.SaveChangesAsync(); return new DeviceStatusDto { Id = device.Id, IpAddress = device.IpAddress, AmtOnline = amtOnline, OsOnline = osOnline }; } /// /// 检测 AMT 是否在线(通过尝试连接AMT端口) /// private async Task<(bool isOnline, List openPorts)> CheckAmtOnlineAsync(string ipAddress) { int[] amtPorts = { 16992, 16993 }; var openPorts = new List(); foreach (var port in amtPorts) { try { using var client = new TcpClient(); var connectTask = client.ConnectAsync(ipAddress, port); // 设置超时时间为2秒(增加超时以应对网络延迟) if (await Task.WhenAny(connectTask, Task.Delay(2000)) == connectTask) { if (client.Connected) { openPorts.Add(port); _logger.LogInformation("Device {Ip} AMT port {Port} is open", ipAddress, port); } } else { _logger.LogInformation("Device {Ip} AMT port {Port} connection timeout", ipAddress, port); } } catch (Exception ex) { _logger.LogInformation("Failed to connect to {Ip}:{Port}: {Error}", ipAddress, port, ex.Message); } } var isOnline = openPorts.Count > 0; _logger.LogInformation("Device {Ip} AMT online: {Online}, open ports: [{Ports}]", ipAddress, isOnline, string.Join(", ", openPorts)); return (isOnline, openPorts); } /// /// 检测操作系统是否在线(通过查询电源状态) /// private async Task CheckOsOnlineAsync(string ipAddress, List openPorts, List credentials) { // 尝试使用所有凭据查询电源状态 foreach (var credential in credentials) { try { var decryptedPassword = _credentialService.DecryptPassword(credential.Password); var powerState = await _powerService.GetPowerStateAsync( ipAddress, credential.Username, decryptedPassword, openPorts); if (powerState.Success) { // PowerState = 2 表示开机(操作系统在运行) var osOnline = powerState.PowerState == 2; _logger.LogInformation("Device {Ip} OS online: {Online} (PowerState: {State} - {StateText})", ipAddress, osOnline, powerState.PowerState, powerState.PowerStateText); return osOnline; } else { _logger.LogWarning("Device {Ip} failed to get power state: {Error}", ipAddress, powerState.Error); } } catch (Exception ex) { _logger.LogWarning("Failed to get power state for {Ip} with credential {User}: {Error}", ipAddress, credential.Username, ex.Message); } } // 如果无法查询电源状态,返回 false _logger.LogWarning("Device {Ip} OS online status unknown (no valid credentials or query failed)", ipAddress); return false; } } /// /// 设备状态DTO /// public class DeviceStatusDto { public long Id { get; set; } public string IpAddress { get; set; } = string.Empty; public bool AmtOnline { get; set; } public bool OsOnline { get; set; } }