Files
Ayay/SHH.CameraSdk/Controllers/MonitorController.cs
2026-01-17 00:03:16 +08:00

178 lines
5.4 KiB
C#

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace SHH.CameraSdk;
/// <summary>
/// 视频源实时状态监控 API 控制器
/// 核心功能:提供相机设备遥测数据查询、单设备详情查询、系统日志查询
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class MonitorController : ControllerBase
{
#region --- (Dependency Injection) ---
private readonly CameraManager _cameraManager;
private readonly ProcessingConfigManager _configManager;
/// <summary>
/// 构造函数:注入 CameraManager 和 IStorageService
/// </summary>
public MonitorController(CameraManager cameraManager, ProcessingConfigManager configManager)
{
_cameraManager = cameraManager;
_configManager = configManager;
}
#endregion
#region --- API (API Endpoints) ---
/// <summary>
/// 获取所有设备及配置 (对应前端 /api/Monitor/all)
/// </summary>
[HttpGet("all")] // <--- 必须明确写上 "all",否则前端找不到
public IActionResult GetAll()
{
var cameras = _cameraManager.GetAllDevices();
var list = cameras.Select(c => new {
c.Id,
Status = c.Status.ToString(),
c.IsPhysicalOnline,
c.RealFps,
c.Width,
c.Height,
c.TotalFrames,
c.Config.Name,
c.Config.IpAddress,
// 务必包含配置信息,供前端回显
ProcessingOptions = _configManager.GetOptions(c.Id)
});
return Ok(list);
}
/// <summary>
/// 获取全量相机实时遥测数据快照
/// 适用场景:监控大屏首页数据看板
/// </summary>
[HttpGet("dashboard")]
public IActionResult GetDashboard()
{
var telemetrySnapshot = _cameraManager.GetTelemetrySnapshot();
return Ok(telemetrySnapshot);
}
/// <summary>
/// 获取指定相机的详细运行指标
/// </summary>
[HttpGet("{id}")]
public IActionResult GetDeviceDetail(long id)
{
var d = _cameraManager.GetDevice(id);
if (d == null) return NotFound($"设备 ID: {id} 不存在");
return Ok(new
{
d.Id,
Status = d.Status.ToString(),
d.IsActived,
d.IsPhysicalOnline,
d.RealFps,
d.Width,
d.Height,
d.TotalFrames,
d.Config.Name,
d.Config.IpAddress,
// --- 新增:将内存中的订阅需求列表传给前端 ---
Requirements = d.Controller.GetCurrentRequirements().Select(r => new {
r.AppId,
r.TargetFps,
r.LastActive,
r.RealFps,
r.Memo,
r.SavePath,
r.Handle,
r.TargetIp,
r.TargetPort,
r.Protocol,
r.Type,
})
});
}
/// <summary>
/// 获取指定相机的实时截图
/// </summary>
[HttpGet("snapshot/{id}")]
public async Task<IActionResult> GetSnapshot(long id)
{
// 假设您有 SnapshotCoordinator 单例,此处保留原逻辑
var imageBytes = await SnapshotCoordinator.Instance.RequestSnapshotAsync(id, 2000);
if (imageBytes == null)
{
return StatusCode(StatusCodes.Status504GatewayTimeout, "截图请求超时或设备未响应");
}
return File(imageBytes, "image/jpeg");
}
/// <summary>
/// 获取指定相机的深度诊断信息(包含持久化的审计日志)
/// </summary>
[HttpGet("diagnose/{id}")]
public async Task<IActionResult> GetDeviceDiagnostic(long id)
{
var device = _cameraManager.GetDevice(id);
if (device == null) return NotFound("设备不存在");
// [修正] 改为从 StorageService 读取文件日志
// 这样即使重启程序,历史日志也能查到
return Ok(new
{
// 基础信息
Id = device.Id,
Status = device.Status.ToString(),
RealFps = device.RealFps,
TotalFrames = device.TotalFrames,
// 实时状态
BasicInfo = device.Config,
RealTimeStats = new
{
device.RealFps,
device.TotalFrames,
device.IsPhysicalOnline,
device.Width,
device.Height
},
});
}
#endregion
[HttpPost("update-processing")]
public IActionResult UpdateProcessing([FromBody] UpdateProcessingRequest request)
{
// 1. 验证设备是否存在 (可选)
// 2. 构造配置对象
var options = new ProcessingOptions
{
EnableShrink = request.EnableShrink,
EnableExpand = request.EnableExpand,
TargetWidth = request.TargetWidth,
TargetHeight = request.TargetHeight,
EnableBrightness = request.EnableBrightness,
Brightness = request.Brightness
};
// 3. 提交给配置管理器 (实时生效)
// 这里的 _configManager 是通过构造函数注入的单例
_configManager.UpdateOptions(request.DeviceId, options);
return Ok(new { msg = $"设备 {request.DeviceId} 配置已更新", time = DateTime.Now });
}
}