fix(#fastRecord): GetPoints API 응답 키를 items로 변경하여 프론트엔드와 호환성 확보
This commit is contained in:
@@ -296,8 +296,8 @@ public class ExperionPointBuilderController : ControllerBase
|
||||
var points = await _dbSvc.GetRealtimePointsAsync();
|
||||
return Ok(new
|
||||
{
|
||||
count = points.Count(),
|
||||
points = points.Select(p => new
|
||||
total = points.Count(),
|
||||
items = points.Select(p => new
|
||||
{
|
||||
id = p.Id,
|
||||
tagName = p.TagName,
|
||||
@@ -655,3 +655,150 @@ public class ExperionHypertableController : ControllerBase
|
||||
: StatusCode(500, new { result.Success, result.Message }));
|
||||
}
|
||||
}
|
||||
|
||||
// ── FastTable / FastRecord ────────────────────────────────────────────────────
|
||||
|
||||
[ApiController]
|
||||
[Route("api/fast")]
|
||||
public class ExperionFastController : ControllerBase
|
||||
{
|
||||
private readonly IExperionFastService _fastSvc;
|
||||
|
||||
public ExperionFastController(IExperionFastService fastSvc)
|
||||
=> _fastSvc = fastSvc;
|
||||
|
||||
/// <summary>새 fastSession 시작</summary>
|
||||
[HttpPost("start")]
|
||||
public async Task<IActionResult> Start([FromBody] FastSessionStartRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var session = await _fastSvc.StartSessionAsync(request);
|
||||
return Ok(new { id = session.Id, name = session.Name, status = session.Status, startedAt = session.StartedAt });
|
||||
}
|
||||
catch (ArgumentException ex) { return BadRequest(new { error = ex.Message }); }
|
||||
catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
/// <summary>세션 중지</summary>
|
||||
[HttpPost("{id:int}/stop")]
|
||||
public async Task<IActionResult> Stop(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _fastSvc.StopSessionAsync(id);
|
||||
return Ok(new { success = true, message = "세션이 중지되었습니다." });
|
||||
}
|
||||
catch (InvalidOperationException ex) { return NotFound(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
/// <summary>세션 목록 조회</summary>
|
||||
[HttpGet("sessions")]
|
||||
public async Task<IActionResult> GetSessions()
|
||||
{
|
||||
var sessions = await _fastSvc.GetSessionsAsync();
|
||||
return Ok(new
|
||||
{
|
||||
total = sessions.Count(),
|
||||
items = sessions.Select(s => new
|
||||
{
|
||||
id = s.Id,
|
||||
name = s.Name,
|
||||
status = s.Status,
|
||||
samplingMs = s.SamplingMs,
|
||||
durationSec = s.DurationSec,
|
||||
tagCount = s.TagList.Length,
|
||||
rowCount = s.RowCount,
|
||||
startedAt = s.StartedAt,
|
||||
endedAt = s.EndedAt,
|
||||
retentionDays = s.RetentionDays,
|
||||
pinned = s.Pinned
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>세션 상세 정보</summary>
|
||||
[HttpGet("{id:int}")]
|
||||
public async Task<IActionResult> GetSession(int id)
|
||||
{
|
||||
var session = await _fastSvc.GetSessionAsync(id);
|
||||
if (session == null) return NotFound();
|
||||
return Ok(new
|
||||
{
|
||||
id = session.Id,
|
||||
name = session.Name,
|
||||
status = session.Status,
|
||||
samplingMs = session.SamplingMs,
|
||||
durationSec = session.DurationSec,
|
||||
tagList = session.TagList,
|
||||
rowCount = session.RowCount,
|
||||
startedAt = session.StartedAt,
|
||||
endedAt = session.EndedAt,
|
||||
retentionDays = session.RetentionDays,
|
||||
pinned = session.Pinned
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>레코드 조회 (Long 포맷)</summary>
|
||||
[HttpGet("{id:int}/records")]
|
||||
public async Task<IActionResult> GetRecords(int id,
|
||||
[FromQuery] DateTime? from,
|
||||
[FromQuery] DateTime? to,
|
||||
[FromQuery] string format = "long")
|
||||
{
|
||||
var result = await _fastSvc.GetRecordsAsync(id, from, to, format);
|
||||
return Ok(new
|
||||
{
|
||||
sessionId = result.SessionId,
|
||||
from = result.From,
|
||||
to = result.To,
|
||||
tagNames = result.TagNames,
|
||||
total = result.TotalCount,
|
||||
items = result.Items.Select(r => new
|
||||
{
|
||||
sessionId = r.SessionId,
|
||||
recordedAt = r.RecordedAt,
|
||||
tagName = r.TagName,
|
||||
value = r.Value
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>CSV Export (스트리밍)</summary>
|
||||
[HttpGet("{id:int}/csv")]
|
||||
public async Task<IActionResult> ExportCsv(int id,
|
||||
[FromQuery] DateTime? from,
|
||||
[FromQuery] DateTime? to)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
await _fastSvc.ExportCsvAsync(id, ms, from, to);
|
||||
ms.Position = 0;
|
||||
return File(ms, "text/csv", $"fast-{id}-{DateTime.Now:yyyyMMddHHmm}.csv");
|
||||
}
|
||||
|
||||
/// <summary>세션 삭제</summary>
|
||||
[HttpDelete("{id:int}")]
|
||||
public async Task<IActionResult> Delete(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _fastSvc.DeleteSessionAsync(id);
|
||||
return Ok(new { success = true, message = "세션이 삭제되었습니다." });
|
||||
}
|
||||
catch (InvalidOperationException ex) { return NotFound(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
/// <summary>세션 고정/해제</summary>
|
||||
[HttpPost("{id:int}/pin")]
|
||||
public async Task<IActionResult> Pin(int id, [FromBody] PinRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _fastSvc.PinSessionAsync(id, request.Pinned);
|
||||
return Ok(new { success = true, pinned = request.Pinned });
|
||||
}
|
||||
catch (InvalidOperationException ex) { return NotFound(new { error = ex.Message }); }
|
||||
}
|
||||
}
|
||||
|
||||
public record PinRequest(bool Pinned);
|
||||
|
||||
Reference in New Issue
Block a user