Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions setup script/sparrow_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ AUDIO_BIRDS_MODEL_FILENAME_FINAL="model.onnx"
REPO_URL="https://github.com/microsoft/SPARROW.git"
CLONE_DIR=""
USE_ROBIN=false
XBEE_FAMILY="${XBEE_FAMILY:-}"

ONBOARDING_URL="https://server.sparrowstudio.azure.com/v1/onboarding"
EMAIL=""
Expand All @@ -118,9 +119,31 @@ command_exists() { command -v "$1" >/dev/null 2>&1; }
install_uuidgen() {
if command_exists uuidgen; then
log "uuidgen already installed."
return 0
fi

mkdir -p /run/uuidd && chmod 755 /run/uuidd
apt-get update -y || log "WARN: apt-get update failed; continuing with cached indexes."

# /usr/bin/uuidgen ships in the uuid-runtime binary package on every
# current Debian release (Bookworm and Trixie both build it from the
# util-linux source; util-linux itself does NOT ship uuidgen).
# Guard the install so set -e doesn't abort before we can log a
# diagnostic that actually helps the operator.
if apt-get install -y uuid-runtime; then
log "Installed uuid-runtime."
else
mkdir -p /run/uuidd && chmod 755 /run/uuidd
apt-get update -y && apt-get install -y uuid-runtime
log "ERROR: 'apt install uuid-runtime' failed."
log " On Debian, /usr/bin/uuidgen is shipped by the uuid-runtime package."
log " If apt reported 'no installation candidate', /etc/apt/sources.list"
log " is likely missing the 'main' component, or set to the wrong suite."
log " Expected entry for Trixie:"
log " deb http://deb.debian.org/debian $(lsb_release -sc 2>/dev/null || echo trixie) main"
log " Fix sources.list, run 'sudo apt-get update', then re-run this script."
Comment thread
Clamps251 marked this conversation as resolved.
fi

if ! command_exists uuidgen; then
return 1
fi
Comment thread
Clamps251 marked this conversation as resolved.
}

Expand Down Expand Up @@ -453,16 +476,40 @@ detect_xbee_port() {
echo "$port"
}

prompt_xbee_family() {
# Honor an env override so headless / repeat runs skip the prompt.
case "${XBEE_FAMILY:-}" in
868|900)
log "XBEE_FAMILY=$XBEE_FAMILY (from env)"
return 0
;;
"") : ;;
*)
log "WARN: XBEE_FAMILY='$XBEE_FAMILY' is invalid; falling back to prompt."
;;
esac

if _yesno "Is the XBee radio an XBee-PRO 900 (rather than the default XBee SX 868)?"; then
XBEE_FAMILY=900
else
XBEE_FAMILY=868
fi
export XBEE_FAMILY
log "XBEE_FAMILY=$XBEE_FAMILY"
}

run_xbee_configure_if_needed() {
[[ "${USE_ROBIN:-false}" == "true" ]] || {
log "ROBIN not in use; skipping xbee_configure.py"
return 0
}

prompt_xbee_family

local xbee_port
xbee_port="$(detect_xbee_port)" || exit 1

log "Running xbee_configure.py for ROBIN on port $xbee_port..."
log "Running xbee_configure.py for ROBIN on port $xbee_port (family=${XBEE_FAMILY:-868})..."
(
cd "$SYSTEM_FOLDER/sparrow"
python xbee_configure.py \
Expand All @@ -472,7 +519,8 @@ run_xbee_configure_if_needed() {
--rf 1 \
--router 0 \
--netid 1234 \
--node SPARROW_MASTER
--node SPARROW_MASTER \
--family "${XBEE_FAMILY:-868}"
)
}

Expand Down
30 changes: 24 additions & 6 deletions sparrow/xbee_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def configure_xbee(
router_mode: int,
network_id_hex: str | None,
node_id: str | None,
family: str = "868",
):
# 1) Probe to find current baud that allows +++
ser = None
Expand Down Expand Up @@ -101,9 +102,16 @@ def configure_xbee(
print(f"Setting CE={router_mode} (routing/messaging mode) ...")
at(ser, f"CE{router_mode}")

# RF data rate: BR=1 for 80kbps (all nodes must match)
print(f"Setting BR={rf_rate} (RF data rate) ...")
at(ser, f"BR{rf_rate}")
# RF data rate: BR=1 for 80kbps (all nodes must match).
# BR is only a valid AT command on the XBee SX 868 family. On the
# XBee-PRO 900 / 900HP families the RF rate is fixed by the firmware
# image loaded on the module (Digi ships separate 10kbps / 200kbps
# firmware builds), so AT BR returns ERROR — skip the command entirely.
if family == "900":
print("Skipping BR: RF rate is fixed by firmware on XBee-PRO 900 family.")
else:
print(f"Setting BR={rf_rate} (RF data rate) ...")
at(ser, f"BR{rf_rate}")

# Optional Network ID (hex). Example: 1234
if network_id_hex:
Expand Down Expand Up @@ -153,12 +161,17 @@ def configure_xbee(
print(f"[WARN] Re-opened at {final_baud} but couldn't re-enter command mode. "
"This can happen if timing is off; API mode may still be set correctly.")
else:
# Read back key params
# Read back key params. Skip BR on 900-family to avoid printing a
# scary-looking BR=ERROR that just reflects the fact BR isn't a
# valid AT command on that family (RF rate is fixed by firmware).
ap = at(ser2, "AP", expect_ok=False)
br = at(ser2, "BR", expect_ok=False)
ce = at(ser2, "CE", expect_ok=False)
bd = at(ser2, "BD", expect_ok=False)
print(f"[VERIFY] AP={ap.strip()} BR={br.strip()} CE={ce.strip()} BD={bd.strip()}")
if family == "900":
print(f"[VERIFY] AP={ap.strip()} BR=n/a(firmware-fixed) CE={ce.strip()} BD={bd.strip()}")
else:
br = at(ser2, "BR", expect_ok=False)
print(f"[VERIFY] AP={ap.strip()} BR={br.strip()} CE={ce.strip()} BD={bd.strip()}")
at(ser2, "CN", expect_ok=False)
ser2.close()

Expand All @@ -176,6 +189,10 @@ def main():
help="CE routing/messaging mode (0=standard router)")
p.add_argument("--netid", default=None, help="Network ID (hex), e.g. 1234 or 0x1234")
p.add_argument("--node", default=None, help="Node identifier (NI), e.g. SPARROW_GATEWAY")
p.add_argument("--family", choices=["868", "900"], default="868",
help="XBee module family. '868' (default) = XBee SX 868. "
"'900' = XBee-PRO 900 / 900HP; skips the BR command since "
Comment thread
Clamps251 marked this conversation as resolved.
"RF rate on that family is fixed by the loaded firmware image.")
args = p.parse_args()

probe = args.probe_baud[:] if args.probe_baud else DEFAULT_PROBE_BAUDS
Expand All @@ -189,6 +206,7 @@ def main():
router_mode=args.router,
network_id_hex=args.netid,
node_id=args.node,
family=args.family,
)
print("[DONE] Configuration complete.")

Expand Down
Loading