102 lines
3.3 KiB
Bash
102 lines
3.3 KiB
Bash
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
export LC_ALL=C
|
|
|
|
CONFIG_FILE="/etc/pi-car-companion/companion.env"
|
|
HOTSPOT_CONNECTION="pi-car-hotspot"
|
|
HOTSPOT_INTERFACE="wlan0"
|
|
UPSTREAM_INTERFACE="wlan1"
|
|
HOTSPOT_ADDRESS="10.42.0.1/24"
|
|
HOTSPOT_SSID="${1:-MG4-Companion}"
|
|
|
|
if [[ ${EUID} -ne 0 ]]; then
|
|
exec sudo -- "$0" "$@"
|
|
fi
|
|
if [[ ! -f "${CONFIG_FILE}" ]]; then
|
|
echo "Pi Car Companion is not installed. Run install.sh first." >&2
|
|
exit 1
|
|
fi
|
|
if [[ ! "${HOTSPOT_SSID}" =~ ^[[:alnum:]_.-]{1,32}$ ]]; then
|
|
echo "The hotspot SSID must contain 1-32 letters, numbers, dots, hyphens, or underscores." >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$(nmcli --get-values GENERAL.STATE device show "${UPSTREAM_INTERFACE}" 2>/dev/null || true)" != 100* ]]; then
|
|
echo "${UPSTREAM_INTERFACE} must be connected to a saved upstream network before failover is enabled." >&2
|
|
echo "Connect it first with: sudo nmcli --ask device wifi connect '<SSID>' ifname ${UPSTREAM_INTERFACE} name upstream-home" >&2
|
|
exit 1
|
|
fi
|
|
|
|
IFS= read -r -s -p "Password for ${HOTSPOT_SSID} (8-63 characters): " hotspot_password
|
|
echo
|
|
if (( ${#hotspot_password} < 8 || ${#hotspot_password} > 63 )) || [[ ! "${hotspot_password}" =~ ^[[:print:]]+$ ]]; then
|
|
echo "The hotspot password must contain 8-63 printable ASCII characters." >&2
|
|
exit 1
|
|
fi
|
|
psk_hex="$(printf '%s\n' "${hotspot_password}" | wpa_passphrase "${HOTSPOT_SSID}" | sed -n 's/^[[:space:]]*psk=//p')"
|
|
if [[ ! "${psk_hex}" =~ ^[[:xdigit:]]{64}$ ]]; then
|
|
echo "The hotspot password could not be converted into a WPA key." >&2
|
|
exit 1
|
|
fi
|
|
|
|
hotspot_file="/etc/NetworkManager/system-connections/${HOTSPOT_CONNECTION}.nmconnection"
|
|
hotspot_uuid="$(uuidgen)"
|
|
temporary_file="$(mktemp)"
|
|
trap 'rm -f -- "${temporary_file}"' EXIT
|
|
cat > "${temporary_file}" <<EOF
|
|
[connection]
|
|
id=${HOTSPOT_CONNECTION}
|
|
uuid=${hotspot_uuid}
|
|
type=wifi
|
|
interface-name=${HOTSPOT_INTERFACE}
|
|
autoconnect=false
|
|
|
|
[wifi]
|
|
band=bg
|
|
mode=ap
|
|
ssid=${HOTSPOT_SSID}
|
|
|
|
[wifi-security]
|
|
key-mgmt=wpa-psk
|
|
psk=${psk_hex}
|
|
|
|
[ipv4]
|
|
address1=${HOTSPOT_ADDRESS}
|
|
method=shared
|
|
|
|
[ipv6]
|
|
method=disabled
|
|
EOF
|
|
if nmcli --get-values NAME connection show | grep -Fxq "${HOTSPOT_CONNECTION}"; then
|
|
nmcli connection delete "${HOTSPOT_CONNECTION}"
|
|
fi
|
|
install -m 0600 -o root -g root "${temporary_file}" "${hotspot_file}"
|
|
nmcli connection load "${hotspot_file}"
|
|
hotspot_password=""
|
|
psk_hex=""
|
|
|
|
set_env() {
|
|
local key="$1"
|
|
local value="$2"
|
|
if grep -q "^${key}=" "${CONFIG_FILE}"; then
|
|
sed -i "s|^${key}=.*|${key}=${value}|" "${CONFIG_FILE}"
|
|
else
|
|
printf '%s=%s\n' "${key}" "${value}" >> "${CONFIG_FILE}"
|
|
fi
|
|
}
|
|
|
|
set_env NETWORK_MANAGER_ENABLED true
|
|
set_env NETWORK_HOTSPOT_INTERFACE "${HOTSPOT_INTERFACE}"
|
|
set_env NETWORK_UPSTREAM_INTERFACE "${UPSTREAM_INTERFACE}"
|
|
set_env NETWORK_HOTSPOT_CONNECTION "${HOTSPOT_CONNECTION}"
|
|
set_env NETWORK_PROBE_TIMEOUT_SECONDS 60
|
|
set_env NETWORK_STABILITY_SECONDS 10
|
|
set_env NETWORK_POLL_SECONDS 5
|
|
|
|
systemctl enable --now pi-car-companion-network.service
|
|
systemctl restart pi-car-companion.service
|
|
|
|
upstream_address="$(nmcli --get-values IP4.ADDRESS device show "${UPSTREAM_INTERFACE}" | head -n 1)"
|
|
echo "Network failover is enabled."
|
|
echo "The dashboard will remain reachable through ${UPSTREAM_INTERFACE} at ${upstream_address:-its current address}."
|
|
echo "The car hotspot is ${HOTSPOT_SSID} and its dashboard address is http://10.42.0.1:8787."
|