- 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>
70 lines
3.6 KiB
C#
70 lines
3.6 KiB
C#
using System.ComponentModel;
|
|
using Dabit.Mcp.Services;
|
|
using DibdProtocol.Protocol;
|
|
using Microsoft.Extensions.Logging;
|
|
using ModelContextProtocol.Server;
|
|
|
|
namespace Dabit.Mcp.Tools;
|
|
|
|
/// <summary>
|
|
/// 표출신호(HUB75 패턴) 설정 도구. ⚠️ 쓰기 — F16 영역(70+ 모델 의존).
|
|
/// 대표 신호만 이름으로 지원하고, 그 외는 send_custom_signal로 raw 코드 전송.
|
|
/// </summary>
|
|
[McpServerToolType]
|
|
public sealed class SignalTools
|
|
{
|
|
private readonly LedControlService _led;
|
|
private readonly ILogger<SignalTools> _log;
|
|
|
|
public SignalTools(LedControlService led, ILogger<SignalTools> log)
|
|
{
|
|
_led = led;
|
|
_log = log;
|
|
}
|
|
|
|
// 대표 표출신호 → HexData 4바이트 (정본 DisplaySignalData 일부). 전체 70+는 send_custom_signal로.
|
|
private static readonly Dictionary<string, byte[]> SignalHexData = new(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["16D-P16D1S11"] = new byte[] { 0x00, 0x10, 0x01, 0x11 },
|
|
["16D-P16D1S10-1"] = new byte[] { 0x00, 0x10, 0x01, 0x01 },
|
|
["08D-P32D1S11"] = new byte[] { 0x00, 0x08, 0x01, 0x11 },
|
|
["08D-P64D1S21"] = new byte[] { 0x00, 0x08, 0x01, 0x21 },
|
|
["04D-P32D2S11"] = new byte[] { 0x00, 0x04, 0x02, 0x11 },
|
|
["04D-P64D1S11"] = new byte[] { 0x00, 0x04, 0x01, 0x11 },
|
|
["32D-P16D1S11"] = new byte[] { 0x00, 0x20, 0x01, 0x11 },
|
|
};
|
|
|
|
[McpServerTool]
|
|
[Description("전광판 표출신호(HUB75 패턴)를 이름으로 설정한다. ⚠️ 쓰기 — 잘못 설정하면 화면이 깨진다. " +
|
|
"지원: 16D-P16D1S11, 16D-P16D1S10-1, 08D-P32D1S11, 08D-P64D1S21, 04D-P32D2S11, 04D-P64D1S11, 32D-P16D1S11. " +
|
|
"목록에 없으면 send_custom_signal을 쓴다. (08D-P64D1S21은 138 IC 스캔 고정)")]
|
|
public async Task<string> SetDisplaySignal(
|
|
[Description("신호 이름. 예: \"16D-P16D1S11\"")] string signalName,
|
|
[Description("색 순서 0~6 (기본 0)")] int colorOrder = 0,
|
|
CancellationToken ct = default)
|
|
{
|
|
if (!SignalHexData.TryGetValue(signalName.Trim(), out var hd))
|
|
return $"지원하지 않는 신호 '{signalName}'. 지원 목록: {string.Join(", ", SignalHexData.Keys)}. 또는 send_custom_signal 사용.";
|
|
|
|
var colorHex = (byte)(Math.Clamp(colorOrder, 0, 6) + 1); // 정본: idx+1
|
|
byte[] payload = { hd[0], hd[1], hd[2], hd[3], colorHex, 0x01 }; // scanHex 기본 0x01(138 IC)
|
|
var resp = await _led.SendHexAsync(HexCommand.SetHub75Pattern, payload, ct, 5000);
|
|
var (ok, msg) = LedControlService.CheckWriteStatus(HexCommand.SetHub75Pattern, resp);
|
|
return ok ? $"표출신호 '{signalName}' 설정 (color={colorOrder})." : $"표출신호 설정 실패 — {msg}";
|
|
}
|
|
|
|
[McpServerTool]
|
|
[Description("사용자 지정 표출신호 코드를 직접 전송한다(고급). ⚠️ 쓰기 — 코드 형식을 정확히 알 때만 사용. 잘못된 값은 화면을 깨뜨릴 수 있다.")]
|
|
public async Task<string> SendCustomSignal(
|
|
[Description("신호 코드 문자열. 예: \"8121\"")] string code,
|
|
CancellationToken ct = default)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(code) || code.Contains('/') || code.Contains("![") || code.Contains("!]"))
|
|
return "유효한 신호 코드가 아닙니다 ('/', '![', '!]' 불가).";
|
|
// 정본: ASCII msgType "44", data 맨 앞 공백 1개 필수
|
|
var resp = await _led.SendAsciiAsync("44", " " + code.Trim(), ct, 5000);
|
|
if (resp is null) return "전송 실패 — 연결 또는 통신 오류.";
|
|
return resp.Result == "F" ? "전광판이 거부했습니다 (Result=F)." : $"사용자 표출신호 '{code}' 전송.";
|
|
}
|
|
}
|