- Agent端优化: * 添加质量档位定义 (Low: 320x180@3fps, High: 1280x720@15fps) * H.264编码器支持动态质量切换 * 屏幕流服务支持按需推流和质量控制 * 添加SignalR信令客户端连接服务器 - 服务器端优化: * 添加StreamSignalingHub处理质量控制信令 * 支持设备注册/注销和监控状态管理 * 支持教师端监控控制和设备选中 - 前端组件: * 创建H264VideoPlayer组件支持H.264和JPEG模式 * 更新学生屏幕监控页面使用新组件 - 性能提升: * 带宽从120Mbps降至6-7Mbps (降低95%) * 监控墙模式: 60台100kbps=6Mbps * 单机放大模式: 1台1Mbps+59台100kbps=6.9Mbps * 无人观看时停止推流节省带宽
196 lines
7.4 KiB
C#
196 lines
7.4 KiB
C#
using DeviceAgent.Services;
|
||
using Microsoft.Extensions.Options;
|
||
|
||
namespace DeviceAgent;
|
||
|
||
public class Worker : BackgroundService
|
||
{
|
||
private readonly ILogger<Worker> _logger;
|
||
private readonly DeviceInfoService _deviceInfoService;
|
||
private readonly ReportService _reportService;
|
||
private readonly ScreenCaptureService _screenCaptureService;
|
||
private readonly ScreenStreamService _screenStreamService;
|
||
private readonly RemoteDesktopService _remoteDesktopService;
|
||
private readonly SignalingClientService _signalingClientService;
|
||
private readonly AgentConfig _config;
|
||
|
||
private string? _cachedUuid;
|
||
private int _heartbeatCounter = 0;
|
||
private int _screenshotCounter = 0;
|
||
|
||
public Worker(
|
||
ILogger<Worker> logger,
|
||
DeviceInfoService deviceInfoService,
|
||
ReportService reportService,
|
||
ScreenCaptureService screenCaptureService,
|
||
ScreenStreamService screenStreamService,
|
||
RemoteDesktopService remoteDesktopService,
|
||
SignalingClientService signalingClientService,
|
||
IOptions<AgentConfig> config)
|
||
{
|
||
_logger = logger;
|
||
_deviceInfoService = deviceInfoService;
|
||
_reportService = reportService;
|
||
_screenCaptureService = screenCaptureService;
|
||
_screenStreamService = screenStreamService;
|
||
_remoteDesktopService = remoteDesktopService;
|
||
_signalingClientService = signalingClientService;
|
||
_config = config.Value;
|
||
}
|
||
|
||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||
{
|
||
_logger.LogInformation("DeviceAgent 服务已启动");
|
||
_logger.LogInformation("服务器地址: {ServerUrl}", _config.ServerUrl);
|
||
_logger.LogInformation("上报间隔: {Interval} 秒", _config.ReportIntervalSeconds);
|
||
_logger.LogInformation("屏幕截图: {Enabled}", _config.ScreenCaptureEnabled ? "启用" : "禁用");
|
||
_logger.LogInformation("实时屏幕流: {Enabled}", _config.ScreenStreamEnabled ? "启用" : "禁用");
|
||
_logger.LogInformation("自动开启远程桌面: {Enabled}", _config.EnableRemoteDesktopOnStart ? "启用" : "禁用");
|
||
|
||
// 自动开启远程桌面
|
||
if (_config.EnableRemoteDesktopOnStart)
|
||
{
|
||
EnableRemoteDesktopOnStartup();
|
||
}
|
||
|
||
// 设置 SignalingClientService 的 ScreenStreamService 引用(避免循环依赖)
|
||
_signalingClientService.SetScreenStreamService(_screenStreamService);
|
||
|
||
// 启动实时屏幕流服务(在后台任务中)
|
||
Task? screenStreamTask = null;
|
||
Task? signalingTask = null;
|
||
if (_config.ScreenStreamEnabled)
|
||
{
|
||
screenStreamTask = Task.Run(() => _screenStreamService.StartAsync(stoppingToken), stoppingToken);
|
||
signalingTask = Task.Run(() => _signalingClientService.StartAsync(stoppingToken), stoppingToken);
|
||
// 等待一小段时间让服务启动
|
||
await Task.Delay(500, stoppingToken);
|
||
}
|
||
|
||
// 启动时立即上报一次完整信息
|
||
await ReportFullInfoAsync();
|
||
|
||
while (!stoppingToken.IsCancellationRequested)
|
||
{
|
||
try
|
||
{
|
||
_heartbeatCounter++;
|
||
_screenshotCounter++;
|
||
|
||
// 每10次心跳上报一次完整信息,其他时候只发心跳
|
||
if (_heartbeatCounter >= 10)
|
||
{
|
||
await ReportFullInfoAsync();
|
||
_heartbeatCounter = 0;
|
||
}
|
||
else if (!string.IsNullOrEmpty(_cachedUuid))
|
||
{
|
||
await _reportService.SendHeartbeatAsync(_cachedUuid);
|
||
}
|
||
|
||
// 屏幕截图上传(根据配置的间隔)- 已禁用,改用实时流
|
||
if (_config.ScreenCaptureEnabled && !string.IsNullOrEmpty(_cachedUuid))
|
||
{
|
||
var screenshotInterval = _config.ScreenCaptureIntervalSeconds / _config.ReportIntervalSeconds;
|
||
if (_screenshotCounter >= screenshotInterval)
|
||
{
|
||
await UploadScreenshotAsync();
|
||
_screenshotCounter = 0;
|
||
}
|
||
}
|
||
|
||
await Task.Delay(TimeSpan.FromSeconds(_config.ReportIntervalSeconds), stoppingToken);
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
break;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "工作循环发生异常");
|
||
await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
|
||
}
|
||
}
|
||
|
||
// 停止屏幕流服务
|
||
if (_config.ScreenStreamEnabled)
|
||
{
|
||
await _screenStreamService.StopAsync();
|
||
await _signalingClientService.StopAsync();
|
||
}
|
||
|
||
_logger.LogInformation("DeviceAgent 服务已停止");
|
||
}
|
||
|
||
private void EnableRemoteDesktopOnStartup()
|
||
{
|
||
try
|
||
{
|
||
if (_remoteDesktopService.IsRemoteDesktopEnabled())
|
||
{
|
||
_logger.LogInformation("远程桌面已启用,端口: {Port}", _remoteDesktopService.GetRdpPort());
|
||
}
|
||
else
|
||
{
|
||
_logger.LogInformation("正在启用远程桌面...");
|
||
if (_remoteDesktopService.EnableRemoteDesktop())
|
||
{
|
||
_logger.LogInformation("远程桌面已成功启用,端口: {Port}", _remoteDesktopService.GetRdpPort());
|
||
}
|
||
else
|
||
{
|
||
_logger.LogWarning("启用远程桌面失败,请检查是否以管理员权限运行");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "启用远程桌面时发生异常");
|
||
}
|
||
}
|
||
|
||
private async Task ReportFullInfoAsync()
|
||
{
|
||
try
|
||
{
|
||
var deviceInfo = _deviceInfoService.GetDeviceInfo();
|
||
_cachedUuid = deviceInfo.Uuid;
|
||
|
||
_logger.LogInformation("收集到设备信息:");
|
||
_logger.LogInformation(" UUID: {Uuid}", deviceInfo.Uuid);
|
||
_logger.LogInformation(" 主机名: {Hostname}", deviceInfo.Hostname);
|
||
_logger.LogInformation(" IP地址: {IpAddress}", deviceInfo.IpAddress);
|
||
_logger.LogInformation(" MAC地址: {MacAddress}", deviceInfo.MacAddress);
|
||
_logger.LogInformation(" 操作系统: {OsName}", deviceInfo.OsName);
|
||
_logger.LogInformation(" CPU: {CpuName}", deviceInfo.CpuName);
|
||
_logger.LogInformation(" 内存: {Memory} MB", deviceInfo.TotalMemoryMB);
|
||
|
||
await _reportService.ReportDeviceInfoAsync(deviceInfo);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "上报完整信息失败");
|
||
}
|
||
}
|
||
|
||
private async Task UploadScreenshotAsync()
|
||
{
|
||
try
|
||
{
|
||
var screenshot = _screenCaptureService.CaptureScreen(
|
||
_config.ScreenCaptureQuality,
|
||
_config.ScreenCaptureMaxWidth);
|
||
|
||
if (screenshot.Length > 0)
|
||
{
|
||
_logger.LogDebug("截图大小: {Size} KB", screenshot.Length / 1024);
|
||
await _reportService.UploadScreenshotAsync(_cachedUuid!, screenshot);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogWarning(ex, "屏幕截图上传失败");
|
||
}
|
||
}
|
||
}
|