A small standalone bridge that lets a phone (or any browser on the same
Wi-Fi) trigger a scan and read back SWR/impedance from a running
AntScopeZ instance, without installing anything on the
phone. It is a separate project -- no changes to AntScopeZ itself.
It works purely as a client of AntScopeZ's existing Remote API
(remoteapi/README.md in the AntScopeZ repo).
There are two separate network hops here, and it matters which one your phone actually uses.
AntScopeZ's own Remote API only ever binds to 127.0.0.1 ("loopback,"
meaning "this same computer, talk to no one else") -- it is never
reachable from your phone, or from any other device, no matter what
Wi-Fi it's on. That's by design, not a bug. So this bridge (AntScopeZ
Web) has to run on the same computer as AntScopeZ itself, and it's
the bridge -- not AntScopeZ -- that your phone talks to:
iPhone Your computer
------ -----------------------------------------------
(Safari) --Wifi--> AntScopeZ-Web (listens on your network:8000)
[ipaddr]:8000 --(127.0.0.1:7443)--> AntScopeZ
- First hop (phone <-> this bridge): goes over your Wi-Fi network, to the computer's IP address and this bridge's port (8000 by default). This is the only address you ever type on the phone.
- Second hop (bridge <-> AntScopeZ): stays entirely inside the one
computer, over
127.0.0.1on AntScopeZ's Remote API port (7443 by default). Your phone never sees this hop or this port at all.
Say the computer running both AntScopeZ and this bridge has LAN IP
192.168.1.42 (find yours with ip addr / ifconfig on Linux/Mac,
or ipconfig on Windows -- look for the address your router assigned,
usually starting 192.168. or 10.).
| Address | Who connects to it | |
|---|---|---|
| AntScopeZ's Remote API | 127.0.0.1:7443 |
only this bridge, on the same computer -- your phone can never reach this |
| This bridge's web UI | 192.168.1.42:8000 |
your phone, over Wi-Fi |
On the phone's browser, you type only:
http://192.168.1.42:8000/
Substitute your computer's own LAN IP for 192.168.1.42, and its own
--listen-port for 8000 if you changed it from the default. Never
type 127.0.0.1 on the phone -- on the phone, that address would mean
"the phone itself," not your computer, so it would never work there.
One shared upstream connection is used for every browser tab/phone attached to the bridge -- everyone sees the same device/measuring state and the same live point stream, regardless of which one (if any) started the scan.
- In AntScopeZ: Settings > General > Enable Remote API (default port 7443). This is ordinary AntScopeZ configuration, not a code change.
- Install dependencies for this project:
pip install -r requirements.txt - Run the bridge on the same machine as AntScopeZ:
Useful flags:
python3 server.py--antscopez-port(if you changed it from 7443),--listen-port(default 8000),-vfor debug logging. Runpython3 server.py --helpfor the rest. - On your phone (same Wi-Fi as the computer), open
http://<this computer's LAN IP>:8000/-- see the worked example above if that's not clear.
- Scan for devices lists whatever AntScopeZ's Remote API currently sees plugged in (HID/serial/NanoVNA), then Connect.
- Set Start/Stop in kHz and a point count, then Scan. SWR updates live as points stream in; the chart plots SWR vs. frequency.
- The status strip shows whether the bridge can reach AntScopeZ ("backend"), whether a device is connected, and whether a sweep is in progress.
- Reloading the page (e.g. re-opening on your phone) replays the last
completed/in-progress sweep via the Remote API's
lastcommand, so you don't lose your place.
- No BLE devices. AntScopeZ's Remote API rejects BLE connects today -- BLE scanning is inherently asynchronous (scan-then-callback) while the API's device lookup is synchronous, and there's a real object-lifetime hazard in how BLE analyzer ownership would have to work through the API's headless connect path. This isn't a gap in this bridge; it's upstream, in AntScopeZ's own Remote API, and documented there too.
- No frequency-range clamping. The Remote API passes your start/stop/points straight to the connected device; if the range is outside what the hardware accepts, the device (not this bridge) decides what happens.
No authentication, no TLS. This is a LAN-only personal tool, matching how the Remote API itself already works (trusts the local network once enabled). Anyone on the same Wi-Fi who knows the port can drive whatever analyzer is connected -- fine for a home/shack network, not something to expose past your router.
server.py-- aiohttp app: serves the static frontend and the/wsWebSocket endpoint browsers talk to.antscopez_client.py--AntScopeZBridge: owns the single upstream NDJSON/TCP connection to AntScopeZ's Remote API, correlates request/reply by the protocol'sidfield, and fans outconnected/disconnected/point/sweep_doneevents to every attached browser.static/-- the frontend:index.html,app.js(WebSocket client- canvas SWR chart),
style.css.
- canvas SWR chart),
- "backend: unreachable" in the status strip -- AntScopeZ isn't
running, its Remote API isn't enabled, or it's on a different port
than this bridge was started with. The bridge retries every few
seconds and recovers automatically once AntScopeZ (with Remote API
enabled) is reachable again -- no need to restart
server.py. - Phone can't reach the page at all -- confirm phone and computer are on the same Wi-Fi network (not one on a guest network that isolates clients), and that nothing (e.g. a firewall) is blocking the port on the computer.
Python 3.10+ (uses X | None type hints), plus aiohttp (see
requirements.txt). No build step and no dependencies at all on the
frontend side -- static/ is plain HTML/CSS/JS.
MIT -- see LICENSE. Unlike AntScopeZ itself, this project vendors no
GPL-licensed components (aiohttp is an ordinary pip runtime
dependency, not statically linked), so there's no combined-license
complication here.
