Skip to content

Repository files navigation

micro-gui

A Windows desktop GUI for testing ESP32-based appliances over UART. It is a graphical frontend over micro-cli (the Go tester in the sibling cli repo, which simulates the MCU side of the appliance UART protocol): every command you click is executed by the real, tested CLI — the GUI reimplements no protocol logic.

The cli repo is a hard read-only dependency: this project never modifies it. See MIRRORING.md for exactly how the GUI maps onto the client, and PLAN.md for the development history and findings.

Purpose

  • Send any protocol command to a connected appliance by clicking it and filling a form — no memorizing shell syntax.
  • Watch decoded TX/RX traffic live in a color-coded, timestamped log.
  • Stay generic: commands, arguments and datapoints are generated from the same JSON schema files the CLI uses, so any appliance the CLI supports, the GUI supports.

Architecture

Three layers, one file each, strictly stacked — each layer only knows the one below it:

┌────────────────────────────────────────────────────────────┐
│ gui.py — presentation (PySide6)                            │
│   MainWindow: top bar ⇔ CLI flags, command list + forms    │
│   ⇔ shell commands, log pane ⇔ shell output.               │
│   QTimer(50 ms) polls the queue below. No protocol logic.  │
├────────────────────────────────────────────────────────────┤
│ microcli.py — bridge                                       │
│   MicroCli (QObject): spawns micro-cli.exe in a ConPTY     │
│   (pywinpty), writes shell command lines, and runs a       │
│   QThread reader that turns terminal output into           │
│   line(kind, text) signal emissions. classify() = the one  │
│   place coupled to the CLI's output wording.               │
├────────────────────────────────────────────────────────────┤
│ schema.py — data                                           │
│   Read-only loader of the cli repo's schema JSON           │
│   (shared_v2.0.0 + appliances/<name>), same merge the CLI  │
│   itself performs. Drives the command list and arg forms.  │
└────────────────────────────────────────────────────────────┘
                          │
                          ▼
        micro-cli.exe  ──UART──►  appliance (ESP32)

Threading: exactly one boundary, expressed in the Qt signal/slot paradigm. MicroCli's QThread reader emits line(kind, text) / terminated signals; the MainWindow slots live in the main thread, so Qt delivers them as queued connections — no explicit queue, no polling, and no widget is ever touched off the main thread.

Why a subprocess instead of importing the Go code: the CLI's packages live under internal/ (sealed to external Go modules) and the repo must not be modified — and wrapping the binary means a CLI upgrade is just swapping the exe. Why a pseudo-terminal instead of pipes: the CLI's interactive shell exits immediately on non-tty stdin (all findings documented in spike_pipe.py). The pty backend is per-OS: ConPTY via pywinpty on Windows, a Unix pty via ptyprocess on Linux — same API, selected at import time in microcli.py.

Files

File Role
gui.py PySide6 window (--selftest for a windowless check)
microcli.py subprocess wrapper (--demo for a self-check)
schema.py schema loader (run directly for a self-check)
spike_pipe.py ConPTY regression check + recorded Phase 0 findings
run-gui.cmd Windows launcher (no console window)
run-gui.sh Linux/macOS launcher
PLAN.md development plan, phase status, findings
MIRRORING.md detailed GUI ⇔ client mapping guide
ARCHITECTURE.drawio visual architecture diagram (open on diagrams.net or with a draw.io IDE extension)

Requirements

  • Windows 10+ (ConPTY) or Linux, Python 3.10+. The OS-dependent parts are isolated to three spots: the pty backend (pywinpty on Windows, ptyprocess on Linux — installed automatically by the platform markers in requirements.txt), the CLI binary name, and the launcher script. Port listing is platform-independent (pyserial's list_ports, used for enumeration only — the CLI opens the port, never the GUI).
  • The CLI binary — by default in this folder (micro-cli.exe / micro-cli; build from the cli repo: go build -o ..\cli-gui\micro-cli.exe .\cmd\micro-cli, or on Linux go build -o ../cli-gui/micro-cli ./cmd/micro-cli). If it isn't found on Connect, the GUI asks you to locate it once and remembers the path in config.json (untracked by git).
  • The cli repo checked out as a sibling (..\cli) for the schema files
  • For real hardware: on Windows, the USB-UART driver for your adapter (CP210x or FTDI VCP — same requirement as the CLI); on Linux, membership in the dialout group to open /dev/ttyUSB*.

Setup

# Windows
cd C:\Repos\FRESCO\cli-gui
python -m venv .venv
.venv\Scripts\python -m pip install -r requirements.txt
# Linux
cd ~/FRESCO/cli-gui
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt

Run

Windows: double-click run-gui.cmd, or .venv\Scripts\python gui.py. Linux: ./run-gui.sh (after chmod +x run-gui.sh), or .venv/bin/python gui.py.

First time on a new platform, run spike_pipe.py — it is the go/no-go check that the pty-driving technique works there (already validated on Windows).

Pick port / baud / appliance in the top bar (check dry-run to try the UI without hardware), click Connect, select a command on the left, fill its arguments, Send. Traffic appears on the right: green = sent, blue = received, red = errors.

Self-checks

All runnable without hardware:

.venv\Scripts\python spike_pipe.py       # ConPTY driving still works
.venv\Scripts\python microcli.py --demo  # wrapper pipeline end-to-end
.venv\Scripts\python schema.py           # schema loading/merge
.venv\Scripts\python gui.py --selftest   # full click path, windowless

Known limitations

  • Dry-run shows TX only. The CLI's -dry-run echo device has a bug (whole packet returned to a 1-byte SLIP read, remainder dropped), so Received: lines can never appear without real hardware. Details in spike_pipe.py.
  • RX display is validated against the known output format but not yet against a live appliance.
  • The log classifier is coupled to micro-cli's output wording; if a CLI release rewords its prints, update microcli.classify().
  • Raw messages longer than ~400 hex chars would wrap in the pseudo-terminal and corrupt line parsing (noted in microcli.py).

About

A python GUI to simulate interaction with a physical device and the micro-iot-firmware

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages