Skip to content

Web UI

mcnanovna includes an optional Three.js-based 3D viewer for antenna radiation patterns.

Enabling the Web UI

Set the MCNANOVNA_WEB_PORT environment variable:

Terminal window
MCNANOVNA_WEB_PORT=8080 uvx mcnanovna

Then open http://localhost:8080 in your browser.

Features

3D Pattern Visualization

  • Interactive rotation with mouse drag
  • Zoom with scroll wheel
  • Gain-mapped color gradient (red = high, blue = low)
  • dBi reference rings

Pattern Sources

  1. From VNA scan: Run radiation_pattern tool
  2. From known impedance: Use radiation_pattern_from_data
  3. File upload: Load CSV, EMCAR, NEC2, or S1P files

Controls

ControlAction
Left dragRotate view
ScrollZoom in/out
Right dragPan
Double-clickReset view

Side Panel

  • Antenna type selector
  • Frequency display
  • Impedance readout
  • Peak gain indicator
  • Toggle reference rings
  • Toggle axes

API Endpoints

The web UI provides REST and WebSocket endpoints:

REST

EndpointMethodDescription
/api/pattern/computePOSTCompute pattern from S11 data
/api/pattern/currentGETGet current pattern data
/api/statusGETServer status

WebSocket

Connect to /ws for real-time pattern updates during measurement.

const ws = new WebSocket('ws://localhost:8080/ws');
ws.onmessage = (event) => {
const pattern = JSON.parse(event.data);
// Update visualization
};

Pattern Format

All patterns use this JSON structure:

{
"antenna_type": "dipole",
"frequency_hz": 145000000,
"theta_deg": [0, 5, 10, ...],
"phi_deg": [0, 10, 20, ...],
"gain_dbi": [-40, -35, -20, ...],
"peak_gain_dbi": 2.15,
"num_points": 6552
}

File Upload

Click “Load File” to import external patterns:

FormatExtensionNotes
CSV.csv2 or 3 columns
EMCAR.datAntenna range format
NEC2.out, .necSimulation output
S1P.s1pTouchstone → analytical

Architecture

┌─────────────────────────────────────────────────────────┐
│ Browser │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Three.js Scene │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │
│ │ │ Pattern Mesh│ │ OrbitControl│ │ Reference │ │ │
│ │ │(gain→color) │ │ (camera) │ │ Rings │ │ │
│ │ └─────────────┘ └─────────────┘ └───────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ │ │
│ HTTP/WebSocket │
│ ▼ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ FastAPI (webui/api.py) │ │
│ │ Pattern compute, WebSocket push │ │
│ └───────────────────────────────────────────────────┘ │
│ │ │
│ Shared NanoVNA │
│ ▼ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ mcnanovna MCP server │ │
│ │ (same process, asyncio.Lock) │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

The web UI runs in a daemon thread sharing the same process as the MCP server. An asyncio.Lock prevents concurrent VNA access from web and MCP.