# Installing FiWiControl **Repository:** **FiWiControl** (checkout directory, mixed case). **Python package / `pip` name:** **`fiwicontrol`** (lowercase). See the **Naming** paragraph at the top of **`README.md`** if that split is confusing. **Requirements:** Python **3.11+**. For SSH automation to rigs, **passwordless** **`root@`** — see **`docs/node-control-asyncio-design.md`**. --- ## Bring up systems (new workstation + lab rig) Use this order the first time you (or someone else) joins the project or replaces a machine. Replace **`192.168.1.39`** with your rig’s IP when needed. | Step | Where | What to do | |------|--------|------------| | 1 | Workstation | **Clone** this repo and **`cd`** into it. | | 2 | Workstation | **Python 3.11+** and an **editable install**: **`python3 -m pip install -e ".[dev]"`**, then **`python3 -m pip install -e ".[power]"`** if you use Acroname/Monsoon or remote power tests (see **Workstation** below). | | 3 | Workstation → rig | **Passwordless SSH as root:** **`ssh -o BatchMode=yes root@192.168.1.39 true`** must exit **0** with no password prompt. On the rig, install your workstation’s **public key** in **`/root/.ssh/authorized_keys`** and ensure **`sshd`** allows **`root`** with pubkey auth. | | 4 | Rig (e.g. Pi) | **`git clone`** the same repo where you will run power/discovery (often **`/root/Code/FiWiControl`**). Your **`--remote-repo`** path must match. | | 5 | Workstation | From your clone, run **`python3 -m fiwicontrol.commands`** with the Pi IP and **`--remote-repo`** (PEP 668 / Raspberry Pi OS needs **`--break-system-packages`** or **`FIWI_REMOTE_PIP_FLAGS`**). See **Remote host setup** below (numbered subsections **3** and **4**: install **`fiwicontrol[power]`** on the rig, then align **`python3`** with **`pip`**). | | 6 | Workstation | **Verify** (minimal): **`python3 -m pytest -q tests/test_package_layout.py`**, then **`FIWI_REMOTE_IP=… python3 -m pytest -q tests/test_node_control.py`**, then **`python3 -m pytest -q tests/test_remote_power_dependencies.py`**. Default **`FIWI_REMOTE_IP`** is **`192.168.1.39`** if unset. Full tree: **`python3 -m pytest tests/ -q`** (expect one **skipped** test unless **`FIWI_VERIFY_POWER_INI=1`**). For INI / **`--verify-inventory`**, see **`docs/power-control-and-inventory.md`** → **“Verification checklist (after install)”**. | **SSH user:** **`ssh_node`** ( **`sshtype="ssh"`** ) always uses an explicit **`root@`** (or whatever **`ssh_session`** **`user`** is set to). It does **not** open **`ssh 192.168.1.39`** with your local login name, so your manual tests should use **`root@…`** as well. **After a `git pull` on the rig:** if the Pi uses an **editable** **`pip install -e`**, pull there before expecting new Python code on the node. --- ## Workstation (e.g. Fedora): recommended install From your clone of this repo, use an **editable install** so **`python3 -m fiwicontrol…`**, **`pytest`**, and **`import fiwicontrol.*`** work from any working directory (use a **venv** if you prefer not to touch system Python): ```bash cd ~/Code/FiWiControl python3 -m pip install -U pip setuptools wheel python3 -m pip install -e ".[dev]" ``` Add **power / USB** dependencies when you work with Acroname or Monsoon discovery locally: ```bash python3 -m pip install -e ".[power]" ``` Or in one line: ```bash python3 -m pip install -e ".[dev,power]" ``` **Why this is the default:** you avoid remembering **`PYTHONPATH=src`**, IDEs and **`python -m`** behave predictably, and it matches how **`pyproject.toml`** / **`pytest`** are meant to be used. ### Without a local install (one-off) If you have **not** run **`pip install -e .`**, you can still run modules from the repo root: ```bash cd ~/Code/FiWiControl PYTHONPATH=src python3 -m pytest tests/test_package_layout.py -q PYTHONPATH=src python3 -m fiwicontrol.power --discovery-json ``` This is easy to **forget** after you **`cd`** elsewhere, so prefer an editable install for day-to-day work. **Summary (workstation):** use **editable install** on your main dev box; use **`PYTHONPATH=src`** when you deliberately skip a local install. --- ## Remote host setup End-to-end steps for a **lab rig** (e.g. Raspberry Pi 5) that **`ssh_node`** and **`fiwicontrol.power`** talk to over **`ssh root@`**. Same SSH user and rules as in **`docs/node-control-asyncio-design.md`** (passwordless **`BatchMode=yes`**). ### 1. SSH from your workstation ```bash ssh -o BatchMode=yes -i ~/.ssh/id_ed25519 root@192.168.1.39 true ``` (no output, exit **0**). If this fails, fix keys and **`/root/.ssh/authorized_keys`** on the rig first. On some Linux workstations, OpenSSH aborts before connecting with **`Bad owner or permissions on …/ssh_config.d/…`** (for example Fedora’s **`20-systemd-ssh-proxy.conf`**). FiWiControl’s pytest session sets **`FIWI_SSH_CONFIG`** to a minimal client file under **`tests/fixtures/`** so **`ssh -F`** skips the system **`/etc/ssh/ssh_config`**. For ad hoc runs (inventory, scripts), export **`FIWI_SSH_CONFIG`** to that same file, or to your own minimal **`ssh_config`** that does not **`Include`** the broken drop-in. ### 2. Repo on the remote The Pi needs a **git checkout** of FiWiControl (same tree you pushed). Example for **`root`**: ```bash # on the Pi (as root) mkdir -p /root/Code cd /root/Code git clone FiWiControl ``` Use your team’s real clone URL. **`--remote-repo`** below must be that directory (e.g. **`/root/Code/FiWiControl`**). ### 3. Install **`fiwicontrol[power]`** on the remote from Fedora Your **Fedora** machine must already run **`python3 -m fiwicontrol.power`** (usually **`pip install -e .`** from your local clone — see above). Then: ```bash cd ~/Code/FiWiControl python3 -m fiwicontrol.commands 192.168.1.39 --remote-repo /root/Code/FiWiControl --break-system-packages ``` **Raspberry Pi OS / Debian (PEP 668):** system Python blocks **`pip install`** without **`--break-system-packages`**. Prefer the **`--break-system-packages`** flag above. **Do not** pass a *separate* token after **`--pip-flags`** if it starts with **`--`** (argparse will treat it as another option). Use either: - **`--break-system-packages`**, or - **`--pip-flags=--break-system-packages`** (equals form), or - **`export FIWI_REMOTE_PIP_FLAGS='--break-system-packages'`** and omit **`--pip-flags`**. **Wrapper:** **`scripts/setup_pi_power.sh`** sets **`PYTHONPATH=src`** on Fedora if needed, then runs **`python3 -m fiwicontrol.commands`** (**`--setup-remote`**-style args) using **`FIWI_REMOTE_IP`** and **`FIWI_REMOTE_REPO`**: ```bash cd ~/Code/FiWiControl chmod +x scripts/setup_pi_power.sh # once export FIWI_REMOTE_IP=192.168.1.39 export FIWI_REMOTE_REPO=/root/Code/FiWiControl export FIWI_REMOTE_PIP_FLAGS='--break-system-packages' ./scripts/setup_pi_power.sh ``` (You can extend the script or pass **`--`** args if you add **`--break-system-packages`** to the script later.) ### 4. Python on the remote (one interpreter for pip and for SSH) If **`pip show fiwicontrol`** reports **`Location: …/python3.11/…`** but plain **`python3`** on the rig is a different version, imports over SSH will fail even though the package is installed. Install and run with the **same** binary, or on Fedora set: ```bash export FIWI_REMOTE_PYTHON=python3.11 # or full path, e.g. /usr/bin/python3.11 ``` That variable is read by **`discover_devices_remote_async`**, **`tests/test_remote_power_dependencies.py`**, and **`python3 -m fiwicontrol.commands … --remote-python …`** (remote setup). ### 5. Verify after install Quick remote sanity (imports + **`python3 -m fiwicontrol.power --discovery-json`** over SSH; needs **`FIWI_REMOTE_IP`** if not **`192.168.1.39`**): ```bash python3 -m pytest -q tests/test_remote_power_dependencies.py ``` **Full checklist for a new machine** (local discovery, **`ssh root@…`**, remote **`fiwicontrol`**, INI editing, **`--list-power-devices`**, **`--verify-inventory`**, optional pytest): **`docs/power-control-and-inventory.md`** → **“Verification checklist (after install)”**. **INI layout** (**`[site]`**, **`[node.*]`**, **`[inventory.host.*]`**, **`acroname`** / **`monsoon_count`**): same doc → **“Lab INI file reference”**. --- ## Quick import check ```bash python3 -c "import fiwicontrol.commands, fiwicontrol.power; print('ok')" ``` With only **`[dev]`** installed, **`fiwicontrol.power`** still imports; hardware discovery needs **`[power]`** ( **`brainstem`**, **`pyserial`** ).