| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- #!/bin/bash
- #
- # Dune Weaver - Autohotspot Setup
- #
- # Sets up the autohotspot system so the Pi creates a "Dune Weaver" WiFi
- # hotspot when no known network is available. Users connect to the hotspot
- # and configure WiFi through the Dune Weaver app.
- #
- # DNS redirect for captive portal is handled by NetworkManager's built-in
- # dnsmasq (via dnsmasq-shared.d config), not a separate dnsmasq instance.
- #
- # Run: bash wifi/setup-wifi.sh
- # Or: dw wifi setup
- #
- set -e
- # Colors
- RED='\033[0;31m'
- GREEN='\033[0;32m'
- YELLOW='\033[1;33m'
- BLUE='\033[0;34m'
- NC='\033[0m'
- # Determine script and project directories
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
- HOTSPOT_CON_NAME="DuneWeaver-Hotspot"
- HOTSPOT_SSID="Dune Weaver"
- HOTSPOT_IP="10.42.0.1/24"
- IFACE="wlan0"
- NM_DNSMASQ_DIR="/etc/NetworkManager/dnsmasq-shared.d"
- print_step() {
- echo -e "\n${BLUE}==>${NC} ${GREEN}$1${NC}"
- }
- print_success() {
- echo -e "${GREEN}$1${NC}"
- }
- print_warning() {
- echo -e "${YELLOW}Warning:${NC} $1"
- }
- print_error() {
- echo -e "${RED}Error:${NC} $1"
- }
- # Check prerequisites
- check_prereqs() {
- print_step "Checking prerequisites..."
- # Check for NetworkManager
- if ! command -v nmcli &>/dev/null; then
- print_error "NetworkManager (nmcli) not found. This requires Pi OS Trixie or later."
- exit 1
- fi
- # Check for wlan0
- if ! nmcli dev show "$IFACE" &>/dev/null; then
- print_warning "WiFi interface '$IFACE' not found. Hotspot may not work."
- fi
- print_success "Prerequisites OK"
- }
- # Create the NetworkManager hotspot connection profile
- create_hotspot_profile() {
- print_step "Creating hotspot connection profile..."
- # Remove existing profile if present
- if nmcli con show "$HOTSPOT_CON_NAME" &>/dev/null; then
- echo "Removing existing hotspot profile..."
- sudo nmcli con delete "$HOTSPOT_CON_NAME" 2>/dev/null || true
- fi
- # Read app name from state.json if available
- local ssid="$HOTSPOT_SSID"
- local state_file="$PROJECT_DIR/state.json"
- if [ -f "$state_file" ]; then
- local app_name
- app_name=$(python3 -c "import json; print(json.load(open('$state_file')).get('app_name', ''))" 2>/dev/null || true)
- if [ -n "$app_name" ]; then
- ssid="$app_name"
- echo "Using app name from state.json: $ssid"
- fi
- fi
- # Create the hotspot profile (open network, no password)
- sudo nmcli con add type wifi ifname "$IFACE" mode ap con-name "$HOTSPOT_CON_NAME" \
- ssid "$ssid" autoconnect no \
- ipv4.method shared ipv4.addresses "$HOTSPOT_IP"
- print_success "Hotspot profile created: SSID='$ssid', IP=${HOTSPOT_IP%/*}"
- }
- # Install DNS redirect config for captive portal
- install_dns_redirect() {
- print_step "Installing DNS redirect for captive portal..."
- # NetworkManager's shared mode runs its own dnsmasq.
- # Configs in dnsmasq-shared.d/ are loaded automatically when a shared
- # connection is active. This redirects ALL DNS to the Pi's hotspot IP,
- # triggering captive portal detection on phones/tablets.
- sudo mkdir -p "$NM_DNSMASQ_DIR"
- sudo cp "$SCRIPT_DIR/dnsmasq-hotspot.conf" "$NM_DNSMASQ_DIR/dune-weaver-captive.conf"
- print_success "DNS redirect installed at $NM_DNSMASQ_DIR/dune-weaver-captive.conf"
- }
- # Copy autohotspot script and service
- install_configs() {
- print_step "Installing autohotspot script..."
- # Copy autohotspot script
- sudo cp "$SCRIPT_DIR/autohotspot" /usr/local/bin/autohotspot
- sudo chmod +x /usr/local/bin/autohotspot
- echo "Installed /usr/local/bin/autohotspot"
- print_success "Autohotspot script installed"
- }
- # Install and enable the systemd service and timer
- install_service() {
- print_step "Installing autohotspot service and timer..."
- # Boot service: runs once at startup with 30s scan
- sudo cp "$SCRIPT_DIR/autohotspot.service" /etc/systemd/system/autohotspot.service
- # Periodic check: runs every 60s to detect WiFi drops and recover
- sudo cp "$SCRIPT_DIR/autohotspot-check.service" /etc/systemd/system/autohotspot-check.service
- sudo cp "$SCRIPT_DIR/autohotspot-check.timer" /etc/systemd/system/autohotspot-check.timer
- sudo systemctl daemon-reload
- sudo systemctl enable autohotspot.service
- sudo systemctl enable --now autohotspot-check.timer
- print_success "autohotspot.service and autohotspot-check.timer installed and enabled"
- }
- # Main
- main() {
- echo -e "${GREEN}Dune Weaver Autohotspot Setup${NC}"
- echo ""
- check_prereqs
- create_hotspot_profile
- install_dns_redirect
- install_configs
- install_service
- echo ""
- echo -e "${GREEN}============================================${NC}"
- echo -e "${GREEN} Autohotspot Setup Complete!${NC}"
- echo -e "${GREEN}============================================${NC}"
- echo ""
- echo "On next boot, the Pi will:"
- echo " 1. Scan for known WiFi networks (30s timeout)"
- echo " 2. If found → connect normally"
- echo " 3. If not found → create a '$(nmcli -t -f 802-11-wireless.ssid con show "$HOTSPOT_CON_NAME" 2>/dev/null | cut -d: -f2 || echo "$HOTSPOT_SSID")' hotspot"
- echo ""
- echo "A periodic check runs every 60 seconds to:"
- echo " - Fall back to hotspot if WiFi drops"
- echo " - Reconnect to known WiFi when it becomes available"
- echo ""
- echo "Users can connect to the hotspot and open the Dune Weaver app"
- echo "to configure WiFi credentials."
- echo ""
- echo "Commands:"
- echo " dw wifi status — Show current WiFi mode"
- echo " dw wifi hotspot — Manually switch to hotspot mode"
- echo " dw wifi scan — Scan for available networks"
- }
- main "$@"
|