feat: add McpScreen phase 2 display tools
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Host smoke test for the Tactility MCP Screen Phase 1 API."""
|
||||
"""Host smoke test for the Tactility MCP Screen Phase 2 API."""
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import socket
|
||||
import struct
|
||||
import urllib.request
|
||||
|
||||
|
||||
@@ -49,6 +51,53 @@ def require_result(response: dict, label: str) -> None:
|
||||
raise RuntimeError(f"{label} returned no result: {response}")
|
||||
|
||||
|
||||
def make_bmp() -> bytes:
|
||||
width = 4
|
||||
height = 4
|
||||
row_size = width * 3
|
||||
pixels = bytearray()
|
||||
colors = [
|
||||
(0, 0, 255),
|
||||
(0, 255, 0),
|
||||
(255, 0, 0),
|
||||
(255, 255, 255),
|
||||
]
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
blue, green, red = colors[(x + y) % len(colors)]
|
||||
pixels.extend((blue, green, red))
|
||||
pixels.extend(b"\0" * ((4 - row_size % 4) % 4))
|
||||
|
||||
offset = 54
|
||||
file_size = offset + len(pixels)
|
||||
header = (
|
||||
b"BM"
|
||||
+ struct.pack("<IHHI", file_size, 0, 0, offset)
|
||||
+ struct.pack("<IIIHHIIIIII", 40, width, height, 1, 24, 0, len(pixels), 0, 0, 0, 0)
|
||||
)
|
||||
return header + pixels
|
||||
|
||||
|
||||
def raw_endpoint(ip: str) -> None:
|
||||
pixels = bytes(
|
||||
[
|
||||
0xF8, 0x00,
|
||||
0x07, 0xE0,
|
||||
0x00, 0x1F,
|
||||
0xFF, 0xFF,
|
||||
]
|
||||
)
|
||||
request = urllib.request.Request(
|
||||
f"http://{ip}/api/screen/raw?x=2&y=2&w=2&h=2",
|
||||
data=pixels,
|
||||
headers={"Content-Type": "application/octet-stream"},
|
||||
method="POST",
|
||||
)
|
||||
with urllib.request.urlopen(request, timeout=5) as response:
|
||||
if response.read() != b"OK":
|
||||
raise RuntimeError("Raw endpoint returned an unexpected response")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--ip", help="Device IP; omit to use UDP discovery")
|
||||
@@ -106,9 +155,73 @@ def main() -> None:
|
||||
},
|
||||
)
|
||||
require_result(drawn, "draw_text")
|
||||
print("Visible draw test sent.")
|
||||
|
||||
print("Phase 1 smoke test passed.")
|
||||
raw_rpc = rpc(
|
||||
ip,
|
||||
5,
|
||||
"tools/call",
|
||||
{
|
||||
"name": "draw_raw_rgb565",
|
||||
"arguments": {
|
||||
"rgb565_base64": base64.b64encode(
|
||||
bytes([0xFF, 0xE0, 0xF8, 0x1F, 0x07, 0xFF, 0x00, 0x00])
|
||||
).decode(),
|
||||
"x": 20,
|
||||
"y": 70,
|
||||
"w": 4,
|
||||
"h": 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
require_result(raw_rpc, "draw_raw_rgb565")
|
||||
|
||||
bmp = rpc(
|
||||
ip,
|
||||
6,
|
||||
"tools/call",
|
||||
{
|
||||
"name": "draw_color_bmp",
|
||||
"arguments": {
|
||||
"bmp_base64": base64.b64encode(make_bmp()).decode(),
|
||||
"x": 30,
|
||||
"y": 90,
|
||||
},
|
||||
},
|
||||
)
|
||||
require_result(bmp, "draw_color_bmp")
|
||||
|
||||
pbm_bytes = b"P4\n8 2\n" + bytes([0b10101010, 0b01010101])
|
||||
pbm = rpc(
|
||||
ip,
|
||||
7,
|
||||
"tools/call",
|
||||
{
|
||||
"name": "draw_image",
|
||||
"arguments": {
|
||||
"pbm_base64": base64.b64encode(pbm_bytes).decode(),
|
||||
"x": 50,
|
||||
"y": 110,
|
||||
},
|
||||
},
|
||||
)
|
||||
require_result(pbm, "draw_image")
|
||||
|
||||
raw_endpoint(ip)
|
||||
|
||||
screenshot = rpc(
|
||||
ip,
|
||||
8,
|
||||
"tools/call",
|
||||
{"name": "get_screenshot", "arguments": {}},
|
||||
)
|
||||
require_result(screenshot, "get_screenshot")
|
||||
screenshot_text = screenshot["result"]["content"][0]["text"]
|
||||
if not screenshot_text.startswith("__PBM_BASE64__:"):
|
||||
raise RuntimeError("Screenshot did not return PBM data")
|
||||
base64.b64decode(screenshot_text.split(":", 1)[1], validate=True)
|
||||
print("Visible Phase 2 draw and screenshot tests sent.")
|
||||
|
||||
print("Phase 2 smoke test passed.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user