even-realities/everything-evenhub

simulator-automation

- Automate the EvenHub glasses simulator via its HTTP API.

소스 보기
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

EvenHub Simulator Automation

The simulator exposes an HTTP API on localhost when launched with --automation-port <PORT>.

bash
evenhub-simulator https://my-app.example.com --automation-port 9898

Base URL: http://127.0.0.1:<PORT>

API Reference

Health check

GET /api/ping
→ "pong"

Glasses screenshot

Returns the current LVGL framebuffer as image/png (576×288, RGBA).

GET /api/screenshot/glasses
→ image/png binary (RGBA)

RGBA format — critical for image analysis:

  • Background pixels: (R=0, G=255, B=0, A=0) — transparent (alpha = 0)
  • Lit/text pixels: (R=0, G=255, B=0, A=255) — opaque (alpha = 255)

Always work in RGBA mode. Do NOT convert to RGB — it drops the alpha channel and makes background pixels indistinguishable from text pixels (both appear as pure green).

python
from PIL import Image
img = Image.open('glasses.png')  # keep as RGBA — do NOT call img.convert('RGB')
pixels = img.load()
# Lit pixel test:
is_lit = lambda px: px[3] > 0   # alpha > 0

Webview screenshot

Captures the main browser webview using html2canvas. Returns image/png. May take a few seconds; times out after 10s.

GET /api/screenshot/webview
→ image/png binary

Console logs

Returns captured console.* output, uncaught exceptions, unhandled promise rejections, and failed fetch calls from the main webview.

GET /api/console
→ { "entries": [...], "total": N }

Each entry:

json
{ "id": 0, "level": "log|warn|error|info|debug|trace", "message": "...", "ts": 1712150400000 }

Prefixes for non-console sources:

  • [uncaught] ... — uncaught exception
  • [unhandledrejection] ... — unhandled promise rejection
  • [fetch] ... — failed fetch (non-ok status or network error)

Poll for new entries only:

GET /api/console?since_id=42
→ entries with id > 42

`since_id` must be a non-negative integer. Passing a negative value (e.g. -1) causes the server to return an error, not an empty list. For the first poll, omit the parameter entirely to retrieve all current entries, then track last_id from the response:

python
# First poll — no since_id
resp = requests.get(f"{BASE_URL}/api/console")
entries = resp.json()["entries"]
last_id = max((e["id"] for e in entries), default=0)

# Subsequent polls
resp = requests.get(f"{BASE_URL}/api/console?since_id={last_id}")

Clear the buffer:

DELETE /api/console

Timing caution: Startup logs (e.g. a "ready" signal) are emitted once and lost if you clear the buffer before reading them. Pattern: poll for the ready signal first, then clear if needed.

python
# Safe: check for ready signal BEFORE clearing
poll_until(target="APP_READY")
requests.delete(f"{BASE_URL}/api/console")  # only if you need a clean slate after

Glasses input

Send a touchpad action to the glasses display.

POST /api/input
Content-Type: application/json

{ "action": "up" | "down" | "click" | "double_click" }

Response: { "ok": true }

Actions map to the glasses touchpad:

  • up / down — scroll through list items or text
  • click — select the current item
  • double_click — triggers a system-level double-click event (typically "back" or "dismiss")

Automation workflow

  1. Verify the server is running: GET /api/ping
  2. Poll for app ready (without clearing console first): look for a known log message.
  3. Observe: Use /api/screenshot/glasses (RGBA) or /api/console to check state.
  4. Act: Send input via POST /api/input. After each action, wait briefly (~300ms) then confirm state changed.
  5. Iterate: Use since_id when polling console to avoid re-reading old entries.

Tips

  • The glasses display is 576×288 pixels, monochrome green. Screenshots are RGBA PNGs.
  • Input only works when the app has created an active event container. If no container is active, input is silently ignored.
  • double_click is typically used to go back or dismiss the current view.
  • Allow 4+ seconds after launching the simulator before polling — SDK init and createStartUpPageContainer take time.

Task

$ARGUMENTS

같은 저장소의 Skills

더 많은 Skills

모든 Skills