feat(mcp): Dabit.Mcp 초기 공개 (리네임 + colors 수정 + scroll 검증)
- refactor: DabitChe.Mcp → Dabit.Mcp (namespace, csproj, exe 모두) - fix: display_message colors를 쉼표 구분 문자열로 변경 (ModelContextProtocol 1.3.0 배열 바인딩 버그 우회) - docs: scroll 4방향(left/right/up/down) 실기 검증 완료 (DIBD600T V3.6.1) 20 도구 (읽기 4 + 콘텐츠 2 + 설정 14), stdio 전송, Windows exe. 실기 검증: scroll/fill_screen 8색/display_message 글자별색 모두 정상. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
72
Dabit.Mcp/Tools/DisplayStatusTools.cs
Normal file
72
Dabit.Mcp/Tools/DisplayStatusTools.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dabit.Mcp.Services;
|
||||
using DibdProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
|
||||
namespace Dabit.Mcp.Tools;
|
||||
|
||||
/// <summary>
|
||||
/// 전광판 상태를 읽는 도구 모음. 모두 읽기 전용 — 표시 내용을 바꾸지 않는다.
|
||||
/// </summary>
|
||||
[McpServerToolType]
|
||||
public sealed class DisplayStatusTools
|
||||
{
|
||||
private readonly LedControlService _led;
|
||||
|
||||
public DisplayStatusTools(LedControlService led)
|
||||
{
|
||||
_led = led;
|
||||
}
|
||||
|
||||
[McpServerTool]
|
||||
[Description("연결된 LED 전광판의 펌웨어 정보(모델/버전/현재 화면 크기 등)를 읽는다. 표시 내용은 변경하지 않는다.")]
|
||||
public async Task<string> 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<string> 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<string> 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()}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user