fix: 修复数据库与SignalR无法连接的问题

This commit is contained in:
SikongJueluo 2025-08-15 13:02:56 +08:00
parent 6fa7fffa7f
commit a00cc84e48
No known key found for this signature in database
20 changed files with 78 additions and 123 deletions

View File

@ -86,7 +86,8 @@ try
var path = context.HttpContext.Request.Path; var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && ( if (!string.IsNullOrEmpty(accessToken) && (
path.StartsWithSegments("/hubs/JtagHub") || path.StartsWithSegments("/hubs/JtagHub") ||
path.StartsWithSegments("/hubs/ProgressHub") path.StartsWithSegments("/hubs/ProgressHub") ||
path.StartsWithSegments("/hubs/DigitalTubesHub")
)) ))
{ {
// Read the token out of the query string // Read the token out of the query string
@ -172,12 +173,6 @@ try
options.OperationProcessors.Add(new OperationSecurityScopeProcessor("Bearer")); options.OperationProcessors.Add(new OperationSecurityScopeProcessor("Bearer"));
}); });
// 添加数据库资源管理器服务
builder.Services.AddScoped<Database.AppDataConnection>();
builder.Services.AddScoped<Database.UserManager>();
builder.Services.AddScoped<Database.ResourceManager>();
builder.Services.AddScoped<Database.ExamManager>();
// 添加 HTTP 视频流服务 // 添加 HTTP 视频流服务
builder.Services.AddSingleton<HttpVideoStreamService>(); builder.Services.AddSingleton<HttpVideoStreamService>();
builder.Services.AddHostedService(provider => provider.GetRequiredService<HttpVideoStreamService>()); builder.Services.AddHostedService(provider => provider.GetRequiredService<HttpVideoStreamService>());
@ -257,9 +252,9 @@ try
// Router // Router
app.MapControllers(); app.MapControllers();
app.MapHub<server.Hubs.JtagHub>("hubs/JtagHub"); app.MapHub<server.Hubs.JtagHub>("/hubs/JtagHub");
app.MapHub<server.Hubs.ProgressHub>("hubs/ProgressHub"); app.MapHub<server.Hubs.ProgressHub>("/hubs/ProgressHub");
app.MapHub<server.Hubs.DigitalTubesHub>("hubs/DigitalTubesHub"); app.MapHub<server.Hubs.DigitalTubesHub>("/hubs/DigitalTubesHub");
// Setup Program // Setup Program
MsgBus.Init(); MsgBus.Init();

View File

@ -18,16 +18,11 @@ public class DataController : ControllerBase
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
// 固定的实验板IP,端口,MAC地址 // 固定的实验板IP,端口,MAC地址
private const string BOARD_IP = "169.254.109.0"; private const string BOARD_IP = "169.254.109.0";
public DataController(Database.UserManager userManager)
{
_userManager = userManager;
}
/// <summary> /// <summary>
/// 获取本机IP地址优先选择与实验板同网段的IP /// 获取本机IP地址优先选择与实验板同网段的IP
/// </summary> /// </summary>

View File

@ -15,12 +15,7 @@ public class DebuggerController : ControllerBase
{ {
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
public DebuggerController(Database.UserManager userManager)
{
this._userManager = userManager;
}
/// <summary> /// <summary>
/// 获取当前用户绑定的调试器实例 /// 获取当前用户绑定的调试器实例

View File

@ -15,19 +15,9 @@ public class ExamController : ControllerBase
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly ExamManager _examManager; private readonly ExamManager _examManager = new();
private readonly ResourceManager _resourceManager; private readonly ResourceManager _resourceManager = new();
private readonly UserManager _userManager; private readonly UserManager _userManager = new();
public ExamController(
ExamManager examManager,
ResourceManager resourceManager,
UserManager userManager)
{
_examManager = examManager;
_resourceManager = resourceManager;
_userManager = userManager;
}
/// <summary> /// <summary>
/// 获取所有实验列表 /// 获取所有实验列表

View File

@ -14,12 +14,11 @@ public class HdmiVideoStreamController : ControllerBase
private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly HttpHdmiVideoStreamService _videoStreamService; private readonly HttpHdmiVideoStreamService _videoStreamService;
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
public HdmiVideoStreamController(HttpHdmiVideoStreamService videoStreamService, Database.UserManager userManager) public HdmiVideoStreamController(HttpHdmiVideoStreamService videoStreamService)
{ {
_videoStreamService = videoStreamService; _videoStreamService = videoStreamService;
_userManager = userManager;
} }
// 管理员获取所有板子的 endpoints // 管理员获取所有板子的 endpoints

View File

@ -17,17 +17,14 @@ public class JtagController : ControllerBase
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly ProgressTrackerService _tracker; private readonly ProgressTrackerService _tracker;
private readonly UserManager _userManager; private readonly UserManager _userManager = new();
private readonly ResourceManager _resourceManager; private readonly ResourceManager _resourceManager = new();
private const string BITSTREAM_PATH = "bitstream/Jtag"; private const string BITSTREAM_PATH = "bitstream/Jtag";
public JtagController( public JtagController(ProgressTrackerService tracker)
ProgressTrackerService tracker, UserManager userManager, ResourceManager resourceManager)
{ {
_tracker = tracker; _tracker = tracker;
_userManager = userManager;
_resourceManager = resourceManager;
} }
/// <summary> /// <summary>

View File

@ -15,12 +15,7 @@ public class LogicAnalyzerController : ControllerBase
{ {
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
public LogicAnalyzerController(Database.UserManager userManager)
{
_userManager = userManager;
}
/// <summary> /// <summary>
/// 获取逻辑分析仪实例 /// 获取逻辑分析仪实例

View File

@ -15,12 +15,7 @@ public class OscilloscopeApiController : ControllerBase
{ {
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
public OscilloscopeApiController(Database.UserManager userManager)
{
_userManager = userManager;
}
/// <summary> /// <summary>
/// 获取示波器实例 /// 获取示波器实例

View File

@ -15,14 +15,8 @@ public class ResourceController : ControllerBase
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly UserManager _userManager; private readonly UserManager _userManager = new();
private readonly ResourceManager _resourceManager; private readonly ResourceManager _resourceManager = new();
public ResourceController(UserManager userManager, ResourceManager resourceManager)
{
_userManager = userManager;
_resourceManager = resourceManager;
}
/// <summary> /// <summary>
/// 添加资源(文件上传) /// 添加资源(文件上传)

View File

@ -18,7 +18,7 @@ public class VideoStreamController : ControllerBase
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly HttpVideoStreamService _videoStreamService; private readonly HttpVideoStreamService _videoStreamService;
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
public class AvailableResolutionsResponse public class AvailableResolutionsResponse
{ {
@ -32,13 +32,10 @@ public class VideoStreamController : ControllerBase
/// 初始化HTTP视频流控制器 /// 初始化HTTP视频流控制器
/// </summary> /// </summary>
/// <param name="videoStreamService">HTTP视频流服务</param> /// <param name="videoStreamService">HTTP视频流服务</param>
/// <param name="userManager">用户管理服务</param> public VideoStreamController(HttpVideoStreamService videoStreamService)
public VideoStreamController(
HttpVideoStreamService videoStreamService, Database.UserManager userManager)
{ {
logger.Info("创建VideoStreamController命名空间{Namespace}", this.GetType().Namespace); logger.Info("创建VideoStreamController命名空间{Namespace}", this.GetType().Namespace);
_videoStreamService = videoStreamService; _videoStreamService = videoStreamService;
_userManager = userManager;
} }
private Optional<string> TryGetBoardId() private Optional<string> TryGetBoardId()

View File

@ -8,12 +8,7 @@ public class ExamManager
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly AppDataConnection _db; private AppDataConnection _db = new();
public ExamManager(AppDataConnection db)
{
this._db = db;
}
/// <summary> /// <summary>
/// 创建新实验 /// 创建新实验

View File

@ -9,12 +9,7 @@ public class ResourceManager
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly AppDataConnection _db; private readonly AppDataConnection _db = new();
public ResourceManager(AppDataConnection db)
{
this._db = db;
}
/// <summary> /// <summary>
/// 根据文件扩展名获取MIME类型 /// 根据文件扩展名获取MIME类型

View File

@ -8,12 +8,7 @@ public class UserManager
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly AppDataConnection _db; private readonly AppDataConnection _db = new();
public UserManager(AppDataConnection db)
{
this._db = db;
}
/// <summary> /// <summary>
/// 添加一个新的用户到数据库 /// 添加一个新的用户到数据库

View File

@ -16,6 +16,7 @@ public interface IDigitalTubesHub
Task<bool> StartScan(); Task<bool> StartScan();
Task<bool> StopScan(); Task<bool> StopScan();
Task<bool> SetFrequency(int frequency); Task<bool> SetFrequency(int frequency);
Task<DigitalTubeTaskStatus> GetStatus();
} }
[Receiver] [Receiver]
@ -24,7 +25,20 @@ public interface IDigitalTubesReceiver
Task OnReceive(byte[] data); Task OnReceive(byte[] data);
} }
class DigitalTubeInfo [TranspilationSource]
public class DigitalTubeTaskStatus
{
public int Frequency { get; set; } = 100;
public bool IsRunning { get; set; } = false;
public DigitalTubeTaskStatus(DigitalTubeInfo info)
{
Frequency = info.Frequency;
IsRunning = info.IsRunning;
}
}
public class DigitalTubeInfo
{ {
public string ClientID { get; set; } public string ClientID { get; set; }
public SevenDigitalTubesCtrl TubeClient { get; set; } public SevenDigitalTubesCtrl TubeClient { get; set; }
@ -46,16 +60,13 @@ public class DigitalTubesHub : Hub<IDigitalTubesReceiver>, IDigitalTubesHub
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly IHubContext<DigitalTubesHub, IDigitalTubesReceiver> _hubContext; private readonly IHubContext<DigitalTubesHub, IDigitalTubesReceiver> _hubContext;
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
private ConcurrentDictionary<string, DigitalTubeInfo> _infoDict = new(); private ConcurrentDictionary<string, DigitalTubeInfo> _infoDict = new();
public DigitalTubesHub( public DigitalTubesHub(IHubContext<DigitalTubesHub, IDigitalTubesReceiver> hubContext)
IHubContext<DigitalTubesHub, IDigitalTubesReceiver> hubContext,
Database.UserManager userManager)
{ {
_hubContext = hubContext; _hubContext = hubContext;
_userManager = userManager;
} }
private Optional<Database.Board> TryGetBoard() private Optional<Database.Board> TryGetBoard()
@ -172,8 +183,8 @@ public class DigitalTubesHub : Hub<IDigitalTubesReceiver>, IDigitalTubesHub
{ {
try try
{ {
if (frequency < 1 || frequency > 1000) if (frequency < 1 || frequency > 1000) return Task.FromException<bool>(
throw new ArgumentException("Frequency must be between 1 and 1000"); new ArgumentException("Frequency must be between 1 and 1000"));
var board = TryGetBoard().OrThrow(() => new Exception("Board not found")); var board = TryGetBoard().OrThrow(() => new Exception("Board not found"));
if (_infoDict.GetOrAdd( if (_infoDict.GetOrAdd(
@ -194,4 +205,29 @@ public class DigitalTubesHub : Hub<IDigitalTubesReceiver>, IDigitalTubesHub
return Task.FromResult(false); return Task.FromResult(false);
} }
} }
public Task<DigitalTubeTaskStatus> GetStatus()
{
try
{
var board = TryGetBoard().OrThrow(() => new Exception("Board not found"));
if (_infoDict.GetOrAdd(
board.ID.ToString(),
(_) => new DigitalTubeInfo(
Context.ConnectionId,
new SevenDigitalTubesCtrl(board.IpAddr, board.Port, 2))
) is DigitalTubeInfo info)
{
return Task.FromResult(new DigitalTubeTaskStatus(info));
}
return Task.FromException<DigitalTubeTaskStatus>(new ArgumentException("Wrong argument"));
}
catch (Exception ex)
{
logger.Error(ex, "Failed to get status");
return Task.FromException<DigitalTubeTaskStatus>(new Exception("Failed to get status"));
}
}
} }

View File

@ -30,15 +30,14 @@ public class JtagHub : Hub<IJtagReceiver>, IJtagHub
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly IHubContext<JtagHub, IJtagReceiver> _hubContext; private readonly IHubContext<JtagHub, IJtagReceiver> _hubContext;
private readonly Database.UserManager _userManager; private readonly Database.UserManager _userManager = new();
private static ConcurrentDictionary<string, int> FreqTable = new(); private static ConcurrentDictionary<string, int> FreqTable = new();
private static ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSourceTable = new(); private static ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSourceTable = new();
public JtagHub(IHubContext<JtagHub, IJtagReceiver> hubContext, Database.UserManager userManager) public JtagHub(IHubContext<JtagHub, IJtagReceiver> hubContext)
{ {
_hubContext = hubContext; _hubContext = hubContext;
_userManager = userManager;
} }
private Optional<Peripherals.JtagClient.Jtag> GetJtagClient(string userName) private Optional<Peripherals.JtagClient.Jtag> GetJtagClient(string userName)

View File

@ -42,7 +42,7 @@ public class SevenDigitalTubesCtrl
if (num < 0 || num > 31) if (num < 0 || num > 31)
throw new ArgumentOutOfRangeException(nameof(num), "Tube number must be between 0 and 31"); throw new ArgumentOutOfRangeException(nameof(num), "Tube number must be between 0 and 31");
var ret = await UDPClientPool.ReadAddr( var ret = await UDPClientPool.ReadAddrByte(
this.ep, this.taskID, SevenDigitalTubesAddr.BASE + (UInt32)num, this.timeout); this.ep, this.taskID, SevenDigitalTubesAddr.BASE + (UInt32)num, this.timeout);
if (!ret.IsSuccessful) if (!ret.IsSuccessful)
{ {

View File

@ -26,17 +26,10 @@ public class HttpHdmiVideoStreamService : BackgroundService
{ {
private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly IServiceProvider _serviceProvider;
private HttpListener? _httpListener; private HttpListener? _httpListener;
private readonly int _serverPort = 4322; private readonly int _serverPort = 4322;
private readonly ConcurrentDictionary<string, HdmiVideoStreamClient> _clientDict = new(); private readonly ConcurrentDictionary<string, HdmiVideoStreamClient> _clientDict = new();
public HttpHdmiVideoStreamService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public override async Task StartAsync(CancellationToken cancellationToken) public override async Task StartAsync(CancellationToken cancellationToken)
{ {
_httpListener = new HttpListener(); _httpListener = new HttpListener();
@ -124,8 +117,7 @@ public class HttpHdmiVideoStreamService : BackgroundService
{ {
if (_clientDict.TryGetValue(boardId, out var client)) return client; if (_clientDict.TryGetValue(boardId, out var client)) return client;
using var scope = _serviceProvider.CreateScope(); var userManager = new Database.UserManager();
var userManager = scope.ServiceProvider.GetRequiredService<Database.UserManager>();
var boardRet = userManager.GetBoardByID(Guid.Parse(boardId)); var boardRet = userManager.GetBoardByID(Guid.Parse(boardId));
if (!boardRet.IsSuccessful || !boardRet.Value.HasValue) if (!boardRet.IsSuccessful || !boardRet.Value.HasValue)
@ -362,8 +354,7 @@ public class HttpHdmiVideoStreamService : BackgroundService
/// <returns>返回所有可用的HDMI视频流终端点列表</returns> /// <returns>返回所有可用的HDMI视频流终端点列表</returns>
public List<HdmiVideoStreamEndpoint>? GetAllVideoEndpoints() public List<HdmiVideoStreamEndpoint>? GetAllVideoEndpoints()
{ {
using var scope = _serviceProvider.CreateScope(); var userManager = new Database.UserManager();
var userManager = scope.ServiceProvider.GetRequiredService<Database.UserManager>();
var boards = userManager.GetAllBoard(); var boards = userManager.GetAllBoard();
if (boards == null) if (boards == null)

View File

@ -95,8 +95,6 @@ public class HttpVideoStreamService : BackgroundService
{ {
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly IServiceProvider _serviceProvider;
private HttpListener? _httpListener; private HttpListener? _httpListener;
private readonly int _serverPort = 4321; private readonly int _serverPort = 4321;
@ -109,11 +107,6 @@ public class HttpVideoStreamService : BackgroundService
private readonly object _usbCameraLock = new object(); private readonly object _usbCameraLock = new object();
#endif #endif
public HttpVideoStreamService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
private Optional<VideoStreamClient> TryGetClient(string boardId) private Optional<VideoStreamClient> TryGetClient(string boardId)
{ {
if (_clientDict.TryGetValue(boardId, out var client)) if (_clientDict.TryGetValue(boardId, out var client))
@ -131,8 +124,7 @@ public class HttpVideoStreamService : BackgroundService
return client; return client;
} }
using var scope = _serviceProvider.CreateScope(); var userManager = new Database.UserManager();
var userManager = scope.ServiceProvider.GetRequiredService<Database.UserManager>();
var boardRet = userManager.GetBoardByID(Guid.Parse(boardId)); var boardRet = userManager.GetBoardByID(Guid.Parse(boardId));
if (!boardRet.IsSuccessful || !boardRet.Value.HasValue) if (!boardRet.IsSuccessful || !boardRet.Value.HasValue)

View File

@ -229,11 +229,11 @@ public class UDPClientPool
public static async ValueTask<Result<RecvDataPackage>> ReadAddr( public static async ValueTask<Result<RecvDataPackage>> ReadAddr(
IPEndPoint endPoint, int taskID, uint devAddr, int dataLength, int timeout = 1000) IPEndPoint endPoint, int taskID, uint devAddr, int dataLength, int timeout = 1000)
{ {
if (dataLength <= 0) if (dataLength <= 0) return new(new ArgumentException(
return new(new ArgumentException("Data length must be greater than 0")); $"Data length must be greater than 0, instead of {dataLength}"));
if (dataLength > 255) if (dataLength > 255) return new(new ArgumentException(
return new(new ArgumentException("Data length must be less than or equal to 255")); $"Data length must be less than or equal to 255, instead of {dataLength}"));
var ret = false; var ret = false;
var opts = new SendAddrPackOptions() var opts = new SendAddrPackOptions()