Move all communication from USB to BLE. The device now advertises as "Claude Controller" and acts as both a BLE HID keyboard (for touch gestures) and a GATT data server (for usage updates from the daemon). - Add NimBLE-Arduino BLE module with custom GATT service + HID keyboard - Add third screen (Bluetooth) with connection status, MAC, reset button - Rewrite daemon in bash using bluetoothctl/busctl for BLE GATT writes - Add screenshot capture via LVGL snapshot over serial - Remove TinyUSB mode — normal pio upload works again - Update README with BLE architecture, screenshots, gesture docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
67 lines
1.6 KiB
Bash
Executable File
67 lines
1.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Take a screenshot from the SC01 Plus display via LVGL snapshot.
|
|
# Usage: ./screenshot.sh [output.png] [port]
|
|
|
|
OUTPUT="${1:-screenshot.png}"
|
|
PORT="${2:-/dev/ttyACM0}"
|
|
|
|
TMPRAW=$(mktemp /tmp/screenshot_XXXXXX.raw)
|
|
trap "rm -f '$TMPRAW'" EXIT
|
|
|
|
echo "Taking screenshot from $PORT..."
|
|
|
|
python3 - "$PORT" "$TMPRAW" << 'PYEOF'
|
|
import serial, sys
|
|
|
|
port_path, raw_path = sys.argv[1], sys.argv[2]
|
|
|
|
port = serial.Serial(port_path, 115200, timeout=10)
|
|
port.reset_input_buffer()
|
|
port.write(b"screenshot\n")
|
|
port.flush()
|
|
|
|
while True:
|
|
line = port.readline().decode("utf-8", errors="replace").strip()
|
|
if line.startswith("SCREENSHOT_START"):
|
|
parts = line.split()
|
|
w, h, raw_size = int(parts[1]), int(parts[2]), int(parts[3])
|
|
break
|
|
if line == "SCREENSHOT_ERR":
|
|
print("Device reported screenshot error", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
data = b""
|
|
while len(data) < raw_size:
|
|
chunk = port.read(min(4096, raw_size - len(data)))
|
|
if not chunk:
|
|
print(f"Timeout: got {len(data)} of {raw_size} bytes", file=sys.stderr)
|
|
sys.exit(1)
|
|
data += chunk
|
|
|
|
with open(raw_path, "wb") as f:
|
|
f.write(data)
|
|
|
|
for _ in range(10):
|
|
line = port.readline().decode("utf-8", errors="replace").strip()
|
|
if line == "SCREENSHOT_END":
|
|
break
|
|
|
|
port.close()
|
|
print(f"Captured {w}x{h} ({len(data)} bytes)")
|
|
PYEOF
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "Screenshot capture failed"
|
|
exit 1
|
|
fi
|
|
|
|
ffmpeg -y -f rawvideo -pixel_format rgb565le -video_size 480x320 \
|
|
-i "$TMPRAW" -update 1 -frames:v 1 "$OUTPUT" 2>/dev/null || true
|
|
|
|
if [ -f "$OUTPUT" ]; then
|
|
echo "Saved: $OUTPUT"
|
|
else
|
|
echo "Error: conversion failed"
|
|
exit 1
|
|
fi
|