using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Peripherals.LogicAnalyzerClient; namespace server.Controllers; /// /// 逻辑分析仪控制器 /// [ApiController] [Route("api/[controller]")] [Authorize] public class LogicAnalyzerController : ControllerBase { private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private readonly Database.UserManager _userManager; public LogicAnalyzerController(Database.UserManager userManager) { _userManager = userManager; } /// /// 获取逻辑分析仪实例 /// private Analyzer? GetAnalyzer() { try { var userName = User.Identity?.Name; if (string.IsNullOrEmpty(userName)) return null; var userRet = _userManager.GetUserByName(userName); if (!userRet.IsSuccessful || !userRet.Value.HasValue) return null; var user = userRet.Value.Value; if (user.BoardID == Guid.Empty) return null; var boardRet = _userManager.GetBoardByID(user.BoardID); if (!boardRet.IsSuccessful || !boardRet.Value.HasValue) return null; var board = boardRet.Value.Value; return new Analyzer(board.IpAddr, board.Port, 0); } catch (Exception ex) { logger.Error(ex, "获取逻辑分析仪实例时发生异常"); return null; } } /// /// 设置捕获模式 /// /// 是否开始捕获 /// 是否强制捕获 /// 操作结果 [HttpPost("SetCaptureMode")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task SetCaptureMode(bool captureOn, bool force = false) { try { var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.SetCaptureMode(captureOn, force); 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("GetCaptureStatus")] [EnableCors("Users")] [ProducesResponseType(typeof(CaptureStatus), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task GetCaptureStatus() { try { var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.ReadCaptureStatus(); 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("SetGlobalTrigMode")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task SetGlobalTrigMode(GlobalCaptureMode mode) { try { var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.SetGlobalTrigMode(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, "操作失败,请稍后重试"); } } /// /// 设置信号触发模式 /// /// 信号索引 (0-7) /// 操作符 /// 信号值 /// 操作结果 [HttpPost("SetSignalTrigMode")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task SetSignalTrigMode(int signalIndex, SignalOperator op, SignalValue val) { try { if (signalIndex < 0 || signalIndex > 31) return BadRequest("信号索引必须在0-31之间"); var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.SetSignalTrigMode(signalIndex, op, val); 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, "操作失败,请稍后重试"); } } /// /// 设置深度、预采样深度、有效通道 /// /// 深度 /// 预采样深度 /// 有效通道(0-[1],1-[2],2-[4],3-[8],4-[16],5-[32]) /// 采样时钟分频系数 /// 操作结果 [HttpPost("SetCaptureParams")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div, AnalyzerClockDiv clock_div) { try { //DDR深度为 32'h01000000 - 32'h0FFFFFFF if (capture_length < 0 || capture_length > 0x10000000 - 0x01000000) return BadRequest("采样深度设置错误"); if (pre_capture_length < 0 || pre_capture_length >= capture_length) return BadRequest("预采样深度必须小于捕获深度"); var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.SetCaptureParams(capture_length, pre_capture_length, channel_div, clock_div); 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("ConfigureCapture")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task ConfigureCapture([FromBody] CaptureConfig config) { try { if (config == null) return BadRequest("配置参数不能为空"); var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); // 设置全局触发模式 var globalResult = await analyzer.SetGlobalTrigMode(config.GlobalMode); if (!globalResult.IsSuccessful) { logger.Error($"设置全局触发模式失败: {globalResult.Error}"); return StatusCode(StatusCodes.Status500InternalServerError, "设置全局触发模式失败"); } // 设置信号触发模式 foreach (var signalConfig in config.SignalConfigs) { if (signalConfig.SignalIndex < 0 || signalConfig.SignalIndex > 31) return BadRequest($"信号索引{signalConfig.SignalIndex}超出范围0-31"); var signalResult = await analyzer.SetSignalTrigMode( signalConfig.SignalIndex, signalConfig.Operator, signalConfig.Value); if (!signalResult.IsSuccessful) { logger.Error($"设置信号{signalConfig.SignalIndex}触发模式失败: {signalResult.Error}"); return StatusCode(StatusCodes.Status500InternalServerError, $"设置信号{signalConfig.SignalIndex}触发模式失败"); } } // 设置深度、预采样深度、有效通道 var paramsResult = await analyzer.SetCaptureParams( config.CaptureLength, config.PreCaptureLength, config.ChannelDiv, config.ClockDiv); if (!paramsResult.IsSuccessful) { logger.Error($"设置深度、预采样深度、有效通道失败: {paramsResult.Error}"); return StatusCode(StatusCodes.Status500InternalServerError, "设置深度、预采样深度、有效通道失败"); } return Ok(true); } catch (Exception ex) { logger.Error(ex, "配置捕获参数时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试"); } } /// /// 强制捕获 /// /// 操作结果 [HttpPost("ForceCapture")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task ForceCapture() { try { var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.SetCaptureMode(true, true); 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, "操作失败,请稍后重试"); } } /// /// 读取捕获数据 /// /// 捕获的波形数据(Base64编码) [HttpGet("GetCaptureData")] [EnableCors("Users")] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task GetCaptureData(int capture_length = 2048 * 32) { try { var analyzer = GetAnalyzer(); if (analyzer == null) return BadRequest("用户未绑定有效的实验板"); var result = await analyzer.ReadCaptureData(capture_length); 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, "操作失败,请稍后重试"); } } /// /// 信号触发配置 /// public class SignalTriggerConfig { /// /// 信号索引 (0-7) /// public int SignalIndex { get; set; } /// /// 操作符 /// public SignalOperator Operator { get; set; } /// /// 信号值 /// public SignalValue Value { get; set; } } /// /// 捕获配置 /// public class CaptureConfig { /// /// 全局触发模式 /// public GlobalCaptureMode GlobalMode { get; set; } /// /// 捕获深度 /// public int CaptureLength { get; set; } = 2048 * 32; /// /// 预采样深度 /// public int PreCaptureLength { get; set; } = 2048; /// /// 有效通道 /// public AnalyzerChannelDiv ChannelDiv { get; set; } = AnalyzerChannelDiv.EIGHT; /// /// 时钟分频系数 /// public AnalyzerClockDiv ClockDiv { get; set; } = AnalyzerClockDiv.DIV1; /// /// 信号触发配置列表 /// public SignalTriggerConfig[] SignalConfigs { get; set; } = Array.Empty(); } }