using System.ComponentModel; using System.Text; using System.Text.RegularExpressions; using Dabit.Mcp.Services; using DibdProtocol.Protocol; using ModelContextProtocol.Server; namespace Dabit.Mcp.Tools; /// /// 전광판 상태를 읽는 도구 모음. 모두 읽기 전용 — 표시 내용을 바꾸지 않는다. /// [McpServerToolType] public sealed class DisplayStatusTools { private readonly LedControlService _led; public DisplayStatusTools(LedControlService led) { _led = led; } [McpServerTool] [Description("연결된 LED 전광판의 펌웨어 정보(모델/버전/현재 화면 크기 등)를 읽는다. 표시 내용은 변경하지 않는다.")] public async Task GetFirmwareInfo(CancellationToken ct = default) { var resp = await _led.SendHexAsync(HexCommand.ReadBoardInfo, [0xF1], ct); if (resp is null || resp.Data.Length == 0) return "펌웨어 정보를 읽지 못했습니다 (응답 없음 또는 연결 실패)."; // 응답 data[0] == 0xF1 (요청 마커 에코)이면 건너뛴다 (FirmwareService 선례) var start = (resp.Data.Length > 1 && resp.Data[0] == 0xF1) ? 1 : 0; var text = Encoding.ASCII.GetString(resp.Data, start, resp.Data.Length - start).TrimEnd('\0', ' '); return string.IsNullOrWhiteSpace(text) ? "펌웨어 정보가 비어 있습니다." : text; } [McpServerTool] [Description("전광판의 현재 화면 크기(가로 x 세로 픽셀)를 읽는다. 펌웨어 정보 응답에서 추출한다.")] public async Task GetScreenSize(CancellationToken ct = default) { var info = await GetFirmwareInfo(ct); // 펌웨어 문자열에서 "96x320" 같은 패턴 추출 (실기 검증 후 정밀화) var m = Regex.Match(info, @"(\d+)\s*[xX]\s*(\d{2,4})"); return m.Success ? $"화면 크기: 가로 {m.Groups[1].Value} x 세로 {m.Groups[2].Value} 픽셀" : $"화면 크기를 펌웨어 응답에서 찾지 못했습니다. 원문: {info}"; } [McpServerTool] [Description("전광판 컨트롤러의 현재 시각(RTC)을 읽는다.")] public async Task GetTime(CancellationToken ct = default) { var resp = await _led.SendHexAsync(HexCommand.ReadTime, [0x00], ct); if (resp is null || resp.Data.Length == 0) return "시간을 읽지 못했습니다 (응답 없음 또는 연결 실패)."; // 응답 7바이트 BCD: [yy, MM, dd, dow, HH, mm, ss] (sync_controller_time과 동일 레이아웃) var d = resp.Data; if (d.Length < 7) return $"시간 응답이 예상보다 짧습니다 (raw {Convert.ToHexString(d)})."; static int FromBcd(byte b) => (b >> 4) * 10 + (b & 0x0F); var year = 2000 + FromBcd(d[0]); return $"컨트롤러 시각: {year}-{FromBcd(d[1]):D2}-{FromBcd(d[2]):D2} {FromBcd(d[4]):D2}:{FromBcd(d[5]):D2}:{FromBcd(d[6]):D2}"; } [McpServerTool] [Description("현재 MCP 서버에 설정된 전광판 연결 정보를 반환한다. 실제 통신은 하지 않는다(연결 점검·스모크용).")] public string GetConnectionStatus() { return $"전광판 연결 설정 — {_led.Settings.Describe()}"; } }