66 lines
3.4 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
feat(mesh): ship archy-rnodeconf on every node, wire daemon tools into deploy RNS's own rnodeconf utility (frequency/bandwidth/spreading-factor/coding-rate read+write, firmware signature verification, board bootstrap) has been the one tool that reliably diagnoses real RNode hardware — it's what finally proved two live nodes were silently running at different spreading factors (SF5 vs SF10, invisible from any of our own probe/logging code, and the actual reason two correctly-flashed radios could detect each other's RF but never decode a packet). Every node should have it, not just whichever one an agent happened to build a throwaway venv on to debug a specific incident. - reticulum-daemon/build.sh: also PyInstaller-package archy-rnodeconf alongside the existing archy-reticulum-daemon, same --collect-submodules/ -d noarchive flags (same RNS.Interfaces __all__-glob requirement applies). - scripts/deploy-to-target.sh: actually wire both packaged binaries into the live deploy path (neither was wired in before — a pre-existing gap noted in docs/RETICULUM-TRANSPORT-PROGRESS.md; this is why reticulum-daemon previously only worked via manual dev-venv setup on rsync-deployed nodes, not the ISO-imaged ones). Non-fatal on build/deploy failure — archipelago already falls back to its dev-venv path if the packaged binary is absent. Also installs the missing `python3.<minor>-venv` package when needed (same "ensurepip not available" gap hit manually twice this session). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 14:44:36 +00:00
# Build the PyInstaller single-binaries for the OTA (plan Phase 1 packaging).
# Outputs: dist/archy-reticulum-daemon, dist/archy-rnodeconf — drop both next
# to /usr/local/bin/archipelago.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
if [ ! -d .venv ]; then
python3 -m venv .venv
fi
.venv/bin/pip install -q -r requirements.txt -r requirements-build.txt
feat(mesh): ship archy-rnodeconf on every node, wire daemon tools into deploy RNS's own rnodeconf utility (frequency/bandwidth/spreading-factor/coding-rate read+write, firmware signature verification, board bootstrap) has been the one tool that reliably diagnoses real RNode hardware — it's what finally proved two live nodes were silently running at different spreading factors (SF5 vs SF10, invisible from any of our own probe/logging code, and the actual reason two correctly-flashed radios could detect each other's RF but never decode a packet). Every node should have it, not just whichever one an agent happened to build a throwaway venv on to debug a specific incident. - reticulum-daemon/build.sh: also PyInstaller-package archy-rnodeconf alongside the existing archy-reticulum-daemon, same --collect-submodules/ -d noarchive flags (same RNS.Interfaces __all__-glob requirement applies). - scripts/deploy-to-target.sh: actually wire both packaged binaries into the live deploy path (neither was wired in before — a pre-existing gap noted in docs/RETICULUM-TRANSPORT-PROGRESS.md; this is why reticulum-daemon previously only worked via manual dev-venv setup on rsync-deployed nodes, not the ISO-imaged ones). Non-fatal on build/deploy failure — archipelago already falls back to its dev-venv path if the packaged binary is absent. Also installs the missing `python3.<minor>-venv` package when needed (same "ensurepip not available" gap hit manually twice this session). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 14:44:36 +00:00
rm -rf build dist archy-reticulum-daemon.spec archy-rnodeconf.spec
# --collect-submodules: RNS/LXMF load most of their own internals dynamically
# (interface drivers, transport backends), which PyInstaller's static import
# analysis can't see from a plain `import RNS`.
#
# -d noarchive is NOT optional: RNS.Interfaces/__init__.py builds its
# `__all__` by glob-ing *.py/*.pyc next to its own `__file__` at import time
# (`from RNS.Interfaces import *` in Reticulum.py relies on that). PyInstaller
# normally zips pure-Python modules into an in-binary PYZ archive, so
# `__file__` doesn't point at a real directory and the glob comes back empty
# -> `NameError: name 'Interface' is not defined` at RNS.Reticulum() bring-up.
# noarchive keeps modules as loose .pyc files on disk so the glob still works.
.venv/bin/pyinstaller --onefile --name archy-reticulum-daemon --clean --noconfirm \
--collect-submodules RNS \
--collect-submodules LXMF \
--collect-data RNS \
-d noarchive \
reticulum_daemon.py
echo "Built dist/archy-reticulum-daemon ($(du -h dist/archy-reticulum-daemon | cut -f1))"
feat(mesh): ship archy-rnodeconf on every node, wire daemon tools into deploy RNS's own rnodeconf utility (frequency/bandwidth/spreading-factor/coding-rate read+write, firmware signature verification, board bootstrap) has been the one tool that reliably diagnoses real RNode hardware — it's what finally proved two live nodes were silently running at different spreading factors (SF5 vs SF10, invisible from any of our own probe/logging code, and the actual reason two correctly-flashed radios could detect each other's RF but never decode a packet). Every node should have it, not just whichever one an agent happened to build a throwaway venv on to debug a specific incident. - reticulum-daemon/build.sh: also PyInstaller-package archy-rnodeconf alongside the existing archy-reticulum-daemon, same --collect-submodules/ -d noarchive flags (same RNS.Interfaces __all__-glob requirement applies). - scripts/deploy-to-target.sh: actually wire both packaged binaries into the live deploy path (neither was wired in before — a pre-existing gap noted in docs/RETICULUM-TRANSPORT-PROGRESS.md; this is why reticulum-daemon previously only worked via manual dev-venv setup on rsync-deployed nodes, not the ISO-imaged ones). Non-fatal on build/deploy failure — archipelago already falls back to its dev-venv path if the packaged binary is absent. Also installs the missing `python3.<minor>-venv` package when needed (same "ensurepip not available" gap hit manually twice this session). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 14:44:36 +00:00
# archy-rnodeconf: RNS's own official RNode config/diagnostic tool
# (RNS.Utilities.rnodeconf — reads/sets frequency, bandwidth, spreading
# factor, coding rate, TX power on an attached RNode; also verifies firmware
# signatures and can flash/bootstrap a board). Shipped alongside the daemon
# so every node can inspect and reconfigure its own radio without needing a
# full RNS/Python dev environment set up by hand — see the checkpoint in
# docs/RETICULUM-TRANSPORT-PROGRESS.md for the incident (two nodes silently
# running at different spreading factors, invisible without this tool) that
# motivated shipping it as a first-class OS tool rather than an ad hoc script.
RNODECONF_SRC="$(find .venv/lib -maxdepth 5 -path '*/site-packages/RNS/Utilities/rnodeconf.py' -print -quit)"
if [ -n "$RNODECONF_SRC" ] && [ -f "$RNODECONF_SRC" ]; then
# --runtime-hook: rnodeconf's own graceful_exit() calls the bare
# exit()/quit() builtins, which only exist in interactive Python (site.py
# injects them) — a frozen app hits NameError right as it tries to quit
# cleanly, after all the real work already succeeded. See
fix(mesh): stop the flash-triggered device boot-loop, fix stuck/wedged jobs Three real incidents from live-testing the flash feature on archy-x250-dev, each traced through logs on the node and fixed at the root: - A failed flash left the mesh listener auto-resuming into a reconnect loop whose backoff reset to its 5s minimum on any momentary connection, even mid-boot-loop — every retry's open() toggles DTR/RTS, which resets many ESP32 boards, so the retries were themselves sustaining the loop. Backoff now only resets after a session runs stably for 20s+, and the flash job no longer auto-resumes the listener after a failure (only on success, after a settle delay). - The HTTP client's blanket 30s request timeout covered entire downloads (Meshtastic's zip is ~170MB), killing large transfers mid-stream; fixed with a per-chunk stall timeout instead of a fixed total-transfer cap. But the download's initial request had no timeout at all, so a slow-to-start server hung it forever — wedging the single-flash-job guard permanently ("already in progress" on every subsequent attempt). Fixed with a bounded wait for the response to start, plus an absolute ceiling around the whole job as a last-resort safety net. - archy-rnodeconf's PyInstaller freeze broke its own internal esptool invocation (sys.executable pointed at the frozen binary itself instead of a real interpreter) — fixed via a new runtime hook. esptool's own auto-reset-into-bootloader handshake is separately known to be flaky on some CP2102/CH340 boards; it now retries once at a conservative baud rate instead of failing outright, and failure logs show the full error chain instead of just the outer context message. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 02:18:55 +00:00
# pyi_rthook_exit_builtins.py. A second hook fixes rnodeconf's board-flash
# step, which shells out to a bundled esptool.py via `sys.executable` —
# under a frozen binary that's the binary itself, not a real interpreter,
# so the flash subprocess call breaks. See
# pyi_rthook_fix_flasher_executable.py.
feat(mesh): ship archy-rnodeconf on every node, wire daemon tools into deploy RNS's own rnodeconf utility (frequency/bandwidth/spreading-factor/coding-rate read+write, firmware signature verification, board bootstrap) has been the one tool that reliably diagnoses real RNode hardware — it's what finally proved two live nodes were silently running at different spreading factors (SF5 vs SF10, invisible from any of our own probe/logging code, and the actual reason two correctly-flashed radios could detect each other's RF but never decode a packet). Every node should have it, not just whichever one an agent happened to build a throwaway venv on to debug a specific incident. - reticulum-daemon/build.sh: also PyInstaller-package archy-rnodeconf alongside the existing archy-reticulum-daemon, same --collect-submodules/ -d noarchive flags (same RNS.Interfaces __all__-glob requirement applies). - scripts/deploy-to-target.sh: actually wire both packaged binaries into the live deploy path (neither was wired in before — a pre-existing gap noted in docs/RETICULUM-TRANSPORT-PROGRESS.md; this is why reticulum-daemon previously only worked via manual dev-venv setup on rsync-deployed nodes, not the ISO-imaged ones). Non-fatal on build/deploy failure — archipelago already falls back to its dev-venv path if the packaged binary is absent. Also installs the missing `python3.<minor>-venv` package when needed (same "ensurepip not available" gap hit manually twice this session). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 14:44:36 +00:00
.venv/bin/pyinstaller --onefile --name archy-rnodeconf --clean --noconfirm \
--collect-submodules RNS \
--collect-data RNS \
--runtime-hook pyi_rthook_exit_builtins.py \
fix(mesh): stop the flash-triggered device boot-loop, fix stuck/wedged jobs Three real incidents from live-testing the flash feature on archy-x250-dev, each traced through logs on the node and fixed at the root: - A failed flash left the mesh listener auto-resuming into a reconnect loop whose backoff reset to its 5s minimum on any momentary connection, even mid-boot-loop — every retry's open() toggles DTR/RTS, which resets many ESP32 boards, so the retries were themselves sustaining the loop. Backoff now only resets after a session runs stably for 20s+, and the flash job no longer auto-resumes the listener after a failure (only on success, after a settle delay). - The HTTP client's blanket 30s request timeout covered entire downloads (Meshtastic's zip is ~170MB), killing large transfers mid-stream; fixed with a per-chunk stall timeout instead of a fixed total-transfer cap. But the download's initial request had no timeout at all, so a slow-to-start server hung it forever — wedging the single-flash-job guard permanently ("already in progress" on every subsequent attempt). Fixed with a bounded wait for the response to start, plus an absolute ceiling around the whole job as a last-resort safety net. - archy-rnodeconf's PyInstaller freeze broke its own internal esptool invocation (sys.executable pointed at the frozen binary itself instead of a real interpreter) — fixed via a new runtime hook. esptool's own auto-reset-into-bootloader handshake is separately known to be flaky on some CP2102/CH340 boards; it now retries once at a conservative baud rate instead of failing outright, and failure logs show the full error chain instead of just the outer context message. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 02:18:55 +00:00
--runtime-hook pyi_rthook_fix_flasher_executable.py \
feat(mesh): ship archy-rnodeconf on every node, wire daemon tools into deploy RNS's own rnodeconf utility (frequency/bandwidth/spreading-factor/coding-rate read+write, firmware signature verification, board bootstrap) has been the one tool that reliably diagnoses real RNode hardware — it's what finally proved two live nodes were silently running at different spreading factors (SF5 vs SF10, invisible from any of our own probe/logging code, and the actual reason two correctly-flashed radios could detect each other's RF but never decode a packet). Every node should have it, not just whichever one an agent happened to build a throwaway venv on to debug a specific incident. - reticulum-daemon/build.sh: also PyInstaller-package archy-rnodeconf alongside the existing archy-reticulum-daemon, same --collect-submodules/ -d noarchive flags (same RNS.Interfaces __all__-glob requirement applies). - scripts/deploy-to-target.sh: actually wire both packaged binaries into the live deploy path (neither was wired in before — a pre-existing gap noted in docs/RETICULUM-TRANSPORT-PROGRESS.md; this is why reticulum-daemon previously only worked via manual dev-venv setup on rsync-deployed nodes, not the ISO-imaged ones). Non-fatal on build/deploy failure — archipelago already falls back to its dev-venv path if the packaged binary is absent. Also installs the missing `python3.<minor>-venv` package when needed (same "ensurepip not available" gap hit manually twice this session). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 14:44:36 +00:00
-d noarchive \
"$RNODECONF_SRC"
echo "Built dist/archy-rnodeconf ($(du -h dist/archy-rnodeconf | cut -f1))"
else
echo "WARNING: rnodeconf.py not found at $RNODECONF_SRC (RNS version mismatch?) — skipping archy-rnodeconf build" >&2
fi