#!/usr/bin/env bash # # pi-hotspot.sh — turn the receiver into a Wi-Fi access point so a sender # can connect directly, without any router in between. # # Usage (on the Pi): # # sudo scripts/pi-hotspot.sh on [--ssid NAME] [--psk KEY] [--band bg|a] # sudo scripts/pi-hotspot.sh off # sudo scripts/pi-hotspot.sh status # # The hotspot takes over the Wi-Fi interface: the Pi leaves your router's # network while it is active. Connect to the SSID from the sending machine; # the Pi is reachable at 10.42.0.1 (SSH, screencast) and the sender gets an # address via the built-in DHCP. Discovery and streaming then run over the # direct link. # # The passphrase is stored in /etc/screencast-hotspot.conf (root only) so # `status` can show it again. set -euo pipefail CONNECTION_NAME="screencast-hotspot" INTERFACE="${SC_HOTSPOT_INTERFACE:-wlan0}" CONFIG_FILE="/etc/screencast-hotspot.conf" log() { printf '\n=== %s\n' "$*"; } die() { printf 'pi-hotspot: error: %s\n' "$*" >&2; exit 1; } require_root() { [ "$(id -u)" = 0 ] || die "run with sudo" } random_passphrase() { if command -v openssl >/dev/null 2>&1; then openssl rand -base64 12 | tr -d '=+/' | head -c 16 else tr -dc 'A-Za-z0-9' /dev/null 2>&1 || die "NetworkManager (nmcli) not found" systemctl is-active --quiet NetworkManager || die "NetworkManager is not running" ip link show "$INTERFACE" >/dev/null 2>&1 || die "interface ${INTERFACE} does not exist" if [ -z "$psk" ]; then psk="$(random_passphrase)" fi log "warning: this takes over ${INTERFACE}; the Pi leaves any router Wi-Fi while the hotspot is active" log "creating hotspot '${ssid}' (WPA2, band ${band})" apt-get install -y --no-install-recommends network-manager dnsmasq-base >/dev/null 2>&1 || true nmcli connection delete "$CONNECTION_NAME" >/dev/null 2>&1 || true nmcli connection add \ type wifi \ ifname "$INTERFACE" \ con-name "$CONNECTION_NAME" \ autoconnect yes \ connection.autoconnect-priority 100 \ 802-11-wireless.ssid "$ssid" \ 802-11-wireless.mode ap \ 802-11-wireless.band "$band" \ 802-11-wireless-security.key-mgmt wpa-psk \ 802-11-wireless-security.psk "$psk" \ ipv4.method shared \ ipv6.method disabled >/dev/null nmcli connection up "$CONNECTION_NAME" >/dev/null umask 077 printf 'ssid=%s\npsk=%s\n' "$ssid" "$psk" >"$CONFIG_FILE" log "hotspot is up" printf ' SSID: %s\n' "$ssid" printf ' Password: %s\n' "$psk" printf ' Pi address: 10.42.0.1 (also announced via mDNS)\n' printf '\nOn the sending machine: connect to the Wi-Fi above, then\n' printf ' screencast --send\n' } cmd_off() { log "removing the hotspot (Wi-Fi returns to normal client mode)" nmcli connection delete "$CONNECTION_NAME" >/dev/null 2>&1 || { log "no hotspot configured" exit 0 } rm -f "$CONFIG_FILE" log "done; the Pi will reconnect to any known router Wi-Fi" } cmd_status() { if [ -f "$CONFIG_FILE" ]; then log "hotspot configuration (${CONFIG_FILE})" grep -E '^(ssid|psk)=' "$CONFIG_FILE" | sed -e 's/^/ /' else log "no hotspot configured (run: sudo scripts/pi-hotspot.sh on)" fi nmcli --get-values NAME,TYPE,DEVICE connection show --active 2>/dev/null | grep wifi | sed 's/^/ /' || true } case "${1:-}" in on) require_root; shift; cmd_on "$@" ;; off) require_root; shift; cmd_off "$@" ;; status) cmd_status ;; *) cat <<'EOF' usage: sudo scripts/pi-hotspot.sh on [--ssid NAME] [--psk KEY] [--band bg|a] sudo scripts/pi-hotspot.sh off sudo scripts/pi-hotspot.sh status EOF exit 1 ;; esac