diff --git a/server/src/Controllers/DebuggerController.cs b/server/src/Controllers/DebuggerController.cs new file mode 100644 index 0000000..f8de240 --- /dev/null +++ b/server/src/Controllers/DebuggerController.cs @@ -0,0 +1,251 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using Peripherals.DebuggerClient; + +namespace server.Controllers; + +/// +/// FPGA调试器控制器 +/// +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class DebuggerController : ControllerBase +{ + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + /// + /// 获取调试器实例 + /// + private DebuggerClient? GetDebugger() + { + try + { + var userName = User.Identity?.Name; + if (string.IsNullOrEmpty(userName)) + return null; + + using var db = new Database.AppDataConnection(); + var userRet = db.GetUserByName(userName); + if (!userRet.IsSuccessful || !userRet.Value.HasValue) + return null; + + var user = userRet.Value.Value; + if (user.BoardID == Guid.Empty) + return null; + + var boardRet = db.GetBoardByID(user.BoardID); + if (!boardRet.IsSuccessful || !boardRet.Value.HasValue) + return null; + + var board = boardRet.Value.Value; + return new DebuggerClient(board.IpAddr, board.Port, 1); + } + catch (Exception ex) + { + logger.Error(ex, "获取调试器实例时发生异常"); + return null; + } + } + + /// + /// 设置捕获模式 + /// + [HttpPost("SetMode")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + public async Task SetMode([FromBody] CaptureMode mode) + { + try + { + var debugger = GetDebugger(); + if (debugger == null) + return BadRequest("用户未绑定有效的实验板"); + + var result = await debugger.SetMode(mode); + if (!result.IsSuccessful) + { + logger.Error($"设置捕获模式失败: {result.Error}"); + return StatusCode(StatusCodes.Status500InternalServerError, "设置捕获模式失败"); + } + + return Ok(result.Value); + } + catch (Exception ex) + { + logger.Error(ex, "设置捕获模式时发生异常"); + return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); + } + } + + /// + /// 启动触发器 + /// + [HttpPost("StartTrigger")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + public async Task StartTrigger() + { + try + { + var debugger = GetDebugger(); + if (debugger == null) + return BadRequest("用户未绑定有效的实验板"); + + var result = await debugger.StartTrigger(); + if (!result.IsSuccessful) + { + logger.Error($"启动触发器失败: {result.Error}"); + return StatusCode(StatusCodes.Status500InternalServerError, "启动触发器失败"); + } + + return Ok(result.Value); + } + catch (Exception ex) + { + logger.Error(ex, "启动触发器时发生异常"); + return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); + } + } + + /// + /// 读取触发器状态标志 + /// + [HttpGet("ReadFlag")] + [EnableCors("Users")] + [ProducesResponseType(typeof(byte), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + public async Task ReadFlag() + { + try + { + var debugger = GetDebugger(); + if (debugger == null) + return BadRequest("用户未绑定有效的实验板"); + + var result = await debugger.ReadFlag(); + if (!result.IsSuccessful) + { + logger.Error($"读取触发器状态标志失败: {result.Error}"); + return StatusCode(StatusCodes.Status500InternalServerError, "读取触发器状态标志失败"); + } + + return Ok(result.Value); + } + catch (Exception ex) + { + logger.Error(ex, "读取触发器状态标志时发生异常"); + return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); + } + } + + /// + /// 清除触发器状态标志 + /// + [HttpPost("ClearFlag")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + public async Task ClearFlag() + { + try + { + var debugger = GetDebugger(); + if (debugger == null) + return BadRequest("用户未绑定有效的实验板"); + + var result = await debugger.ClearFlag(); + if (!result.IsSuccessful) + { + logger.Error($"清除触发器状态标志失败: {result.Error}"); + return StatusCode(StatusCodes.Status500InternalServerError, "清除触发器状态标志失败"); + } + + return Ok(result.Value); + } + catch (Exception ex) + { + logger.Error(ex, "清除触发器状态标志时发生异常"); + return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); + } + } + + /// + /// 读取捕获数据 + /// + [HttpGet("ReadData")] + [EnableCors("Users")] + [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + public async Task ReadData([FromQuery] ushort offset = 0) + { + try + { + var debugger = GetDebugger(); + if (debugger == null) + return BadRequest("用户未绑定有效的实验板"); + + var result = await debugger.ReadData(offset); + if (!result.IsSuccessful) + { + logger.Error($"读取捕获数据失败: {result.Error}"); + return StatusCode(StatusCodes.Status500InternalServerError, "读取捕获数据失败"); + } + + // 返回Base64编码 + var base64Data = Convert.ToBase64String(result.Value); + return Ok(base64Data); + } + catch (Exception ex) + { + logger.Error(ex, "读取捕获数据时发生异常"); + return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); + } + } + + /// + /// 刷新调试器状态 + /// + [HttpPost("Refresh")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + public async Task Refresh() + { + try + { + var debugger = GetDebugger(); + if (debugger == null) + return BadRequest("用户未绑定有效的实验板"); + + var result = await debugger.Refresh(); + if (!result.IsSuccessful) + { + logger.Error($"刷新调试器状态失败: {result.Error}"); + return StatusCode(StatusCodes.Status500InternalServerError, "刷新调试器状态失败"); + } + + return Ok(result.Value); + } + catch (Exception ex) + { + logger.Error(ex, "刷新调试器状态时发生异常"); + return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); + } + } +} diff --git a/src/APIClient.ts b/src/APIClient.ts index bc9e52f..b9c507e 100644 --- a/src/APIClient.ts +++ b/src/APIClient.ts @@ -1637,6 +1637,362 @@ export class DDSClient { } } +export class DebuggerClient { + private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { + this.http = http ? http : window as any; + this.baseUrl = baseUrl ?? "http://127.0.0.1:5000"; + } + + /** + * 设置捕获模式 + */ + setMode(mode: string): Promise { + let url_ = this.baseUrl + "/api/Debugger/SetMode"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(mode); + + let options_: RequestInit = { + body: content_, + method: "POST", + headers: { + "Content-Type": "application/json", + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processSetMode(_response); + }); + } + + protected processSetMode(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status === 401) { + return response.text().then((_responseText) => { + let result401: any = null; + let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result401 = ProblemDetails.fromJS(resultData401); + return throwException("A server side error occurred.", status, _responseText, _headers, result401); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 启动触发器 + */ + startTrigger(): Promise { + let url_ = this.baseUrl + "/api/Debugger/StartTrigger"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processStartTrigger(_response); + }); + } + + protected processStartTrigger(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status === 401) { + return response.text().then((_responseText) => { + let result401: any = null; + let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result401 = ProblemDetails.fromJS(resultData401); + return throwException("A server side error occurred.", status, _responseText, _headers, result401); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 读取触发器状态标志 + */ + readFlag(): Promise { + let url_ = this.baseUrl + "/api/Debugger/ReadFlag"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "GET", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processReadFlag(_response); + }); + } + + protected processReadFlag(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status === 401) { + return response.text().then((_responseText) => { + let result401: any = null; + let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result401 = ProblemDetails.fromJS(resultData401); + return throwException("A server side error occurred.", status, _responseText, _headers, result401); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 清除触发器状态标志 + */ + clearFlag(): Promise { + let url_ = this.baseUrl + "/api/Debugger/ClearFlag"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processClearFlag(_response); + }); + } + + protected processClearFlag(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status === 401) { + return response.text().then((_responseText) => { + let result401: any = null; + let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result401 = ProblemDetails.fromJS(resultData401); + return throwException("A server side error occurred.", status, _responseText, _headers, result401); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 读取捕获数据 + * @param offset (optional) + */ + readData(offset: number | undefined): Promise { + let url_ = this.baseUrl + "/api/Debugger/ReadData?"; + if (offset === null) + throw new Error("The parameter 'offset' cannot be null."); + else if (offset !== undefined) + url_ += "offset=" + encodeURIComponent("" + offset) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "GET", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processReadData(_response); + }); + } + + protected processReadData(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status === 401) { + return response.text().then((_responseText) => { + let result401: any = null; + let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result401 = ProblemDetails.fromJS(resultData401); + return throwException("A server side error occurred.", status, _responseText, _headers, result401); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 刷新调试器状态 + */ + refresh(): Promise { + let url_ = this.baseUrl + "/api/Debugger/Refresh"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processRefresh(_response); + }); + } + + protected processRefresh(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status === 401) { + return response.text().then((_responseText) => { + let result401: any = null; + let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result401 = ProblemDetails.fromJS(resultData401); + return throwException("A server side error occurred.", status, _responseText, _headers, result401); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } +} + export class JtagClient { private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; private baseUrl: string; diff --git a/src/components/WaveformDisplay/WaveformDisplay.vue b/src/components/WaveformDisplay/WaveformDisplay.vue index 3650595..91549eb 100644 --- a/src/components/WaveformDisplay/WaveformDisplay.vue +++ b/src/components/WaveformDisplay/WaveformDisplay.vue @@ -2,12 +2,12 @@
-
-

- 暂无逻辑分析数据 -

-
+ +