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:
insulee
2026-06-02 11:20:49 +09:00
parent 94dd74bd5c
commit 640c9a3380
109 changed files with 7146 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
using System.ComponentModel;
using Dabit.Mcp.Services;
using DibdProtocol.Protocol;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
namespace Dabit.Mcp.Tools;
/// <summary>화면 크기·채우기·배경이미지 설정 도구. ⚠️ 쓰기.</summary>
[McpServerToolType]
public sealed class ScreenTools
{
private readonly LedControlService _led;
private readonly ILogger<ScreenTools> _log;
public ScreenTools(LedControlService led, ILogger<ScreenTools> log)
{
_led = led;
_log = log;
}
// 색 인덱스 0~7 → RGB332 colorByte (정본 SettingsViewModel, R[2:0]G[5:3]B[7:6])
private static readonly byte[] FillColors = { 0x00, 0x07, 0x38, 0x3F, 0xC0, 0xC7, 0xF8, 0xFF };
private static readonly string[] ColorNames = { "검정", "빨강", "초록", "노랑", "파랑", "분홍", "청록", "하양" };
// bpp 입력(0/1/2) → payload byte (정본: 0→0x02, 2→0x08, 그 외→0x03=3bpp 8색 기본)
private static byte BppByte(int bpp) => bpp switch { 0 => 0x02, 2 => 0x08, _ => 0x03 };
[McpServerTool]
[Description("전광판 화면 크기(단/열)를 설정한다. ⚠️ 쓰기·설정 저장. layout은 모듈 배열(0~5).")]
public async Task<string> SetScreenSize(
[Description("단(행) 수 1~16")] int rows,
[Description("열 수 1~32")] int cols,
[Description("색심도 0/1/2 (기본 1=3bpp 8색)")] int bpp = 1,
[Description("배열 0~5 (기본 0)")] int layout = 0,
CancellationToken ct = default)
{
byte[] payload = { BppByte(bpp), (byte)Math.Clamp(rows, 1, 16), (byte)Math.Clamp(cols, 1, 32), (byte)Math.Clamp(layout, 0, 5), 0x00, 0xF1 };
var resp = await _led.SendHexAsync(HexCommand.SetScreenSize, payload, ct, 5000);
var (ok, msg) = LedControlService.CheckWriteStatus(HexCommand.SetScreenSize, resp);
if (!ok) return $"화면 크기 설정 실패 — {msg}";
// 응답 [0xF1, rows, cols] — 실제 적용된 값
return resp!.Data.Length >= 3
? $"화면 크기 설정됨: {resp.Data[1]}단 x {resp.Data[2]}열."
: "화면 크기 설정됨.";
}
[McpServerTool]
[Description("전광판 전체를 단색으로 채운다. ⚠️ 쓰기 — 현재 화면을 덮어쓴다. color 0~7: 0검정 1빨강 2초록 3노랑 4파랑 5분홍 6청록 7하양.")]
public async Task<string> FillScreen(
[Description("색 인덱스 0~7 (0검정 1빨강 2초록 3노랑 4파랑 5분홍 6청록 7하양)")] int color,
[Description("색심도 0/1/2 (기본 1)")] int bpp = 1,
CancellationToken ct = default)
{
if (color < 0 || color > 7)
return "색 인덱스는 0~7이어야 합니다 (0검정 1빨강 2초록 3노랑 4파랑 5분홍 6청록 7하양).";
byte[] payload = { BppByte(bpp), FillColors[color], 0x00, 0x00, 0x00 };
var resp = await _led.SendHexAsync(HexCommand.FillScreen, payload, ct, 5000);
var (ok, msg) = LedControlService.CheckWriteStatus(HexCommand.FillScreen, resp);
return ok ? $"화면 채움: {ColorNames[color]}." : $"화면 채우기 실패 — {msg}";
}
[McpServerTool]
[Description("저장된 배경이미지를 불러와 표시한다. ⚠️ 쓰기. num 0~255 (0=사용 안 함).")]
public async Task<string> LoadBackgroundImage(
[Description("이미지 번호 0~255 (0=사용 안 함)")] int num,
CancellationToken ct = default)
{
if (num < 0 || num > 255)
return "이미지 번호는 0~255여야 합니다.";
var resp = await _led.SendHexAsync(HexCommand.LoadBackgroundImage, new[] { (byte)num }, ct, 5000);
var (ok, msg) = LedControlService.CheckWriteStatus(HexCommand.LoadBackgroundImage, resp);
if (!ok) return $"배경이미지 로드 실패 — {msg}";
return num == 0 ? "배경이미지 사용 안 함으로 설정." : $"배경이미지 {num}번 로드.";
}
}