Code for managing, monitoring and testing Umber Fi-Wi networks
Go to file
Robert McMahon 48d7618506 chore: remove Broadcom references; Umber Apache header on flows.py
Made-with: Cursor
2026-04-10 19:17:03 -07:00
configs refactor: move lab discovery to fiwicontrol.lab; remote setup to commands 2026-04-10 18:39:43 -07:00
docs docs: refresh pytest examples, SSH notes, and default.ini paths 2026-04-10 18:51:17 -07:00
scripts refactor: move lab discovery to fiwicontrol.lab; remote setup to commands 2026-04-10 18:39:43 -07:00
src/fiwicontrol chore: remove Broadcom references; Umber Apache header on flows.py 2026-04-10 19:17:03 -07:00
tests test: always run remote power integration tests (remove skipUnless) 2026-04-10 18:46:31 -07:00
.gitignore Initial import: fiwicontrol package (commands + power scaffold) 2026-04-10 11:36:23 -07:00
LICENSE license: Umber copyright header and complete Apache-2.0 appendix 2026-04-10 19:16:02 -07:00
README.md chore: remove Broadcom references; Umber Apache header on flows.py 2026-04-10 19:17:03 -07:00
pyproject.toml refactor: move lab discovery to fiwicontrol.lab; remote setup to commands 2026-04-10 18:39:43 -07:00

README.md

FiWiControl

Tools, libraries and statistical software for automating, managing, monitoring and testing Umber FiWi networks.

Naming: The Git repository and checkout directory are FiWiControl (mixed case). The Python distribution and import package are fiwicontrol (all lowercase, PEP 8) — same project, different casing rules for Git vs Python. Use fiwicontrol for pip install / import, not FiWiControl.

This repository ships that distribution (fiwicontrol on PyPI / pip) with import root fiwicontrol:

  1. fiwicontrol.commands — run commands on remote rigs via OpenSSH or ush (Command, CommandManager, ssh_node). Remote Pi bootstrap: python3 -m fiwicontrol.commands <ip> --remote-repo … (see docs/install.md). Must not import fiwicontrol.power.
  2. fiwicontrol.lab — USB discovery (Acroname / Monsoon) and configs/*.ini inventory load + verify. Imports fiwicontrol.commands for SSH discovery only.
  3. fiwicontrol.powerPower (.on() / .off() / .voltage() / …) via AcronamePower and MonsoonPower, plus a small CLI (--discovery-json, --list-power-devices, --verify-inventory with -c). Re-exports fiwicontrol.lab discovery/inventory for compatibility. May import fiwicontrol.commands and fiwicontrol.lab; the reverse is forbidden.
  4. fiwicontrol.flows — async iperf-driven traffic flows over ssh (remote server/client processes, sampling, histogram / KS tooling). Lives in flows/flows.py. Depends on SciPy, NumPy, Matplotlib, and a compatible iperf binary on endpoints—use pip install -e ".[flows]" when you need it; import fiwicontrol.flows alone stays lightweight (lazy load). Not yet integrated with ssh_node or iperf 2 on Pi 5 roadmap text above—that wiring is follow-on work.

Near-term focus: PCIe hot-swap testing

A first concrete goal for this stack is to support PCIe hot-swap (hot-plug) testing in the lab: controlled remove / restore of the link, predictable enumeration and driver behavior, and repeatable runs across builds and rigs.

That work fails if the bench is informal—wrong port, wrong power path, or no shared picture of what was connected when. FiWiControl targets that gap by combining documented inventory (INI + --verify-inventory), remote automation (ssh_node, python3 -m fiwicontrol.commands to bring up rigs), and programmable power / USB paths (fiwicontrol.power) so sequences are scripted and checkable before the PCIe harness runs. Longer term, SPC (below) is meant for many hot-plug cycles—spotting drift in failure rates or side metrics—not only general FiWi bring-up.

Lab fleet: Raspberry Pi 5 and iperf 2 (planned)

We expect a fleet of Raspberry Pi 5 boards to act as controllers and actuators in the lab: remote fiwicontrol install, discovery over SSH, PCIe / FiWi harness hosts (docs already assume Pi-class rigs). Those Pi 5s will run iperf 2 as synthetic traffic endpoints—controlled load and measurement during FiWi and bring-up experiments, not one-off manual runs. None of this is automated in-repo yet beyond what you can already drive by hand over ssh_node; first-class orchestration and reporting are roadmap.

ESP32, IEEE 802.11, and advanced telemetry (planned)

Separately from the Pi 5 iperf plane, we plan ESP32-based nodes for advanced telemetry, including rich use of IEEE 802.11 (WiFi): airlink statistics, channel / PHY-adjacent metrics, retries, timing, and correlation with harness and inventory state. The goal is lab- and field-grade 802.11 telemetry, not only GPIO or serial counters. This stack is not implemented yet in fiwicontrol; todays code is still the commands / lab / power packages above.

ush expansion (planned)

Expanded ush orchestration alongside OpenSSH—not only the ush transport already wired through ssh_node, but first-class tooling for benches that standardize on ush. Roadmap only beyond todays transport path.

Product differentiation

We expect advanced telemetry (including 802.11-centric, e.g. ESP32, data) and advanced use of iperf 2 on Raspberry Pi 5 hosts—patterns tied to rig state, inventory, and (eventually) SPC, not ad hoc throughput screenshots—to help differentiate Umber FiWi products in the market.

Statistical process control (planned)

The project is intended to grow statistical process control (SPC) support—for example Hotelling-style multivariate monitoring and Shewhart control charts—for lab and field metrics tied to FiWi rigs (including high-volume PCIe hot-swap campaigns where you need to know if the process is still in control). That code is not in the tree yet; todays packages focus on automation, inventory, and power/USB control as described above.

Layout

FiWiControl/
├── LICENSE
├── README.md
├── pyproject.toml
├── docs/
│   ├── install.md
│   ├── node-control-asyncio-design.md
│   └── power-control-and-inventory.md
├── src/
│   └── fiwicontrol/
│       ├── commands/
│       │   ├── __init__.py
│       │   ├── __main__.py
│       │   ├── node_control.py
│       │   └── remote_setup.py
│       ├── lab/
│       │   ├── __init__.py
│       │   ├── discovery.py
│       │   ├── inventory_config.py
│       │   └── inventory_verify.py
│       └── power/
│           ├── __init__.py
│           ├── __main__.py
│           ├── acroname.py
│           ├── control.py
│           └── monsoon.py
└── tests/

Requirements

  • Python 3.11+
  • For sshtype="ssh": passwordless SSH to root@<host> (non-interactive ssh; see docs/node-control-asyncio-design.md).

Install

First-time / new machine: follow docs/install.md“Bring up systems (new workstation + lab rig)”, then the Workstation and Remote host setup sections.

Full guide (workstation, remote host setup for the Pi, pip install -e, PYTHONPATH=src, scripts/setup_pi_power.sh): docs/install.md.

Minimal editable install from the repo root:

cd ~/Code/FiWiControl
python3 -m pip install -e ".[dev]"
# optional: power / USB discovery (Acroname, Monsoon)
python3 -m pip install -e ".[power]"

Imports:

from fiwicontrol.commands import ssh_node, Command, CommandManager

Tests

After install, use the ordered verification checklist and INI reference in docs/power-control-and-inventory.md (sections “Verification checklist (after install)” and “Lab INI file reference”).

Commands, example pytest output, and unittest entry points for node_control: docs/node-control-asyncio-design.md → section “Running tests” (top-level ## heading near the top of the file).

Whole suite (from repo root; pyproject.toml adds src to PYTHONPATH for pytest):

cd ~/Code/FiWiControl
python3 -m pytest tests/ -q

Example summary when the opt-in live INI test is not enabled ( FIWI_VERIFY_POWER_INI unset — one test skipped):

.....s......................                                                                                          [100%]
27 passed, 1 skipped in 18.20s

Run a single test by id (replace with a name from python3 -m pytest tests/<file>.py --collect-only -q):

python3 -m pytest tests/test_package_layout.py::test_import_subpackages -v

Layout / import smoke (no network):

cd ~/Code/FiWiControl
python3 -m pytest tests/test_package_layout.py -q

Remote integration (needs FIWI_REMOTE_IP and key auth):

cd ~/Code/FiWiControl
FIWI_REMOTE_IP=192.168.1.39 python3 -m pytest tests/test_node_control.py -q

Power / USB inventory (needs brainstem and pyserial, e.g. pip install -e ".[power]"): see docs/power-control-and-inventory.md. Lab layout is configs/default.ini by default (override with -c). configs/clubhouse.ini is an alternate example file.

cd ~/Code/FiWiControl
python3 -m pip install -e ".[power]"
python3 -m fiwicontrol.power --verify-inventory
# or: python3 -m fiwicontrol.power -c configs/clubhouse.ini --verify-inventory

The same check from pytest (set FIWI_VERIFY_POWER_INI=1 or pytest skips the live INI test):

FIWI_VERIFY_POWER_INI=1 python3 -m pytest -q tests/test_inventory_verify_live.py

Remote package sanity (imports + python3 -m fiwicontrol.power --discovery-json) for the host in FIWI_REMOTE_IP (default 192.168.1.39):

python3 -m pytest -q tests/test_remote_power_dependencies.py

Example when SSH and the rig are configured (-v; line spacing may vary):

tests/test_remote_power_dependencies.py::TestRemotePowerDependencies::test_remote_imports_fiwicontrol_power_brainstem_serial PASSED [ 50%]
tests/test_remote_power_dependencies.py::TestRemotePowerDependencies::test_remote_power_module_discovery_json PASSED [100%]

============================== 2 passed in 0.65s ==============================

Remote (Gitea)

git remote add origin "https://git.umbernetworks.com/rjmcmahon/FiWiControl.git"
git push -u origin main

Use a Gitea personal access token as the HTTPS password if prompted.