using Microsoft.AspNetCore.Mvc; using OpcUaManager.Models; using OpcUaManager.Services; namespace OpcUaManager.Controllers; [ApiController] [Route("api/database")] [Produces("application/json")] public class DatabaseController : ControllerBase { private readonly DatabaseService _dbSvc; private readonly ILogger _logger; public DatabaseController(DatabaseService dbSvc, ILogger logger) { _dbSvc = dbSvc; _logger = logger; } /// /// DB 연결을 테스트합니다. /// [HttpPost("test")] [ProducesResponseType(200)] [ProducesResponseType(typeof(ApiError), 400)] public async Task Test([FromBody] DbWriteRequest req) { var (ok, msg) = await _dbSvc.TestConnectionAsync(req); return ok ? Ok(new { Message = msg }) : BadRequest(new ApiError { Error = "연결 실패", Detail = msg }); } /// /// opc_history 테이블을 없으면 생성합니다. /// [HttpPost("init")] [ProducesResponseType(200)] [ProducesResponseType(typeof(ApiError), 400)] public async Task Init([FromBody] DbWriteRequest req) { var (ok, msg) = await _dbSvc.EnsureTableAsync(req); return ok ? Ok(new { Message = msg }) : BadRequest(new ApiError { Error = "테이블 초기화 실패", Detail = msg }); } /// /// OPC 태그를 지정 횟수만큼 읽어 DB에 저장합니다 (원본 5회 루프). /// /// /// Sample request: /// /// POST /api/database/write /// { /// "tagNodeId": "ns=1;s=shinam:p-6102.hzset.fieldvalue", /// "tagName": "p-6102", /// "count": 5, /// "intervalMs": 2000, /// "dbHost": "localhost", /// "dbName": "opcdb", /// "dbUser": "postgres", /// "dbPassword": "postgres" /// } /// [HttpPost("write")] [ProducesResponseType(typeof(DbWriteResult), 200)] [ProducesResponseType(typeof(ApiError), 400)] public async Task Write([FromBody] DbWriteRequest req) { if (string.IsNullOrWhiteSpace(req.TagNodeId) || string.IsNullOrWhiteSpace(req.TagName)) return BadRequest(new ApiError { Error = "필수값 누락", Detail = "TagNodeId, TagName 은 필수입니다." }); req.Count = Math.Clamp(req.Count, 1, 100); _logger.LogInformation("DB 저장 시작: {Tag} × {Count}회", req.TagName, req.Count); var result = await _dbSvc.WriteLoopAsync(req); return result.Success ? Ok(result) : BadRequest(new ApiError { Error = "저장 실패", Detail = result.Message }); } /// /// opc_history 테이블의 최근 레코드를 조회합니다. /// [HttpPost("query")] [ProducesResponseType(typeof(DbQueryResult), 200)] [ProducesResponseType(typeof(ApiError), 400)] public async Task Query([FromBody] DbWriteRequest req, [FromQuery] int limit = 100) { var result = await _dbSvc.QueryRecentAsync(req, limit); return result.Success ? Ok(result) : BadRequest(new ApiError { Error = "조회 실패", Detail = result.Message }); } }