Implement notetaking app, ST7796 display with touch support, audio beep navigation, and video streaming
This commit is contained in:
+60
-4
@@ -5,13 +5,14 @@ import time
|
||||
class MCPServer:
|
||||
"""A lightweight JSON-RPC HTTP server implementing Model Context Protocol (MCP) endpoints."""
|
||||
|
||||
def __init__(self, display, led, battery, sensor, rtc, ble):
|
||||
def __init__(self, display, led, battery, sensor, rtc, ble, vstream=None):
|
||||
self.display = display
|
||||
self.led = led
|
||||
self.battery = battery
|
||||
self.sensor = sensor
|
||||
self.rtc = rtc
|
||||
self.ble = ble
|
||||
self.vstream = vstream
|
||||
|
||||
self.sock = None
|
||||
self.active_led_mode = "off" # static, breath, rainbow, off
|
||||
@@ -128,7 +129,7 @@ class MCPServer:
|
||||
"tools": [
|
||||
{
|
||||
"name": "clear_screen",
|
||||
"description": "Clear the 400x300 screen to white (0) or black (1).",
|
||||
"description": "Clear the 480x320 screen to white (0) or black (1).",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -144,8 +145,8 @@ class MCPServer:
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {"type": "string", "description": "The message to display"},
|
||||
"x": {"type": "integer", "description": "X coordinate (0-390)"},
|
||||
"y": {"type": "integer", "description": "Y coordinate (0-290)"},
|
||||
"x": {"type": "integer", "description": "X coordinate (0-470)"},
|
||||
"y": {"type": "integer", "description": "Y coordinate (0-310)"},
|
||||
"size": {"type": "integer", "enum": [1, 2], "description": "Text scale (1=normal, 2=large)"}
|
||||
},
|
||||
"required": ["text", "x", "y"]
|
||||
@@ -297,6 +298,21 @@ class MCPServer:
|
||||
},
|
||||
"required": ["url", "filename"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_video_streaming_instructions",
|
||||
"description": "Get detailed instructions and sample Python code to stream video directly into the RLCD screen using TCP or UDP.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {"type": "string", "enum": ["tcp", "udp", "both"], "description": "The streaming protocol to query (default 'both')"}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_stream_stats",
|
||||
"description": "Get real-time device-side performance and frame-rate statistics for the TCP/UDP video stream.",
|
||||
"inputSchema": {"type": "object", "properties": {}}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -568,5 +584,45 @@ class MCPServer:
|
||||
else:
|
||||
raise RuntimeError(f"Failed to download file from '{url}'.")
|
||||
|
||||
elif name == "get_video_streaming_instructions":
|
||||
protocol = str(args.get("protocol", "both")).lower()
|
||||
|
||||
instructions = [
|
||||
"### RP2350 TFT Video Streaming Instructions",
|
||||
"Dimensions: 400x300 (decoded and centered automatically on the 480x320 screen), 1-bit monochrome (Floyd-Steinberg dithered).",
|
||||
"Frame Buffer Size: 15,000 bytes. The host must convert and map standard pixels into the specific RLCD hardware buffer layout before sending.",
|
||||
"Mapping logic (Python):",
|
||||
" def map_to_rlcd(pil_img):",
|
||||
" img_1bit = pil_img.convert('1', dither=1)",
|
||||
" px = img_1bit.load()",
|
||||
" buf = bytearray(15000)",
|
||||
" for y in range(300):",
|
||||
" for x in range(400):",
|
||||
" if px[x, y]:",
|
||||
" inv_y = 299 - y",
|
||||
" bx = x // 2",
|
||||
" by = inv_y // 4",
|
||||
" idx = bx * 75 + by",
|
||||
" lx, ly = x % 2, inv_y % 4",
|
||||
" bit = 7 - (ly * 2 + lx)",
|
||||
" buf[idx] |= (1 << bit)",
|
||||
" return buf"
|
||||
]
|
||||
|
||||
if protocol in ("tcp", "both"):
|
||||
instructions.append("\n**TCP Streaming (Port 8081):**")
|
||||
instructions.append("Open a TCP connection to the device's IP on port 8081 and send consecutive 15,000-byte frame blocks.")
|
||||
|
||||
if protocol in ("udp", "both"):
|
||||
instructions.append("\n**UDP Streaming / Broadcast (Port 8082):**")
|
||||
instructions.append("Split the 15,000-byte frame into 15 chunks of 1,000 bytes each. Send each chunk as a 1002-byte packet: byte 0 = frame_id (0-255), byte 1 = chunk_idx (0-14), bytes 2..1001 = chunk payload. Send to port 8082 (unicast or broadcast).")
|
||||
|
||||
return "\n".join(instructions)
|
||||
|
||||
elif name == "get_stream_stats":
|
||||
if self.vstream is None:
|
||||
return json.dumps({"error": "Video stream server not initialized."})
|
||||
return json.dumps(self.vstream.get_stats())
|
||||
|
||||
else:
|
||||
raise ValueError(f"Unknown tool: {name}")
|
||||
|
||||
Reference in New Issue
Block a user