- 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>
77 lines
3.9 KiB
C#
77 lines
3.9 KiB
C#
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}번 로드.";
|
|
}
|
|
}
|