Files
openwrt-ha-presence/install.sh
T
2026-10-12 13:49:01 +03:00

294 lines
12 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# OpenWrt HA Presence Tracker Installer
set -e
GITEA_RAW_URL="https://git.darkmode.duckdns.org/sirmrak/openwrt-ha-presence/raw/branch/main/files"
CONFIG_FILE="/etc/config/openwrt_ha"
STATES_DIR="/tmp/mqtt_ha_states"
info() { echo "[INFO] $1"; }
warn() { echo "[WARN] $1"; }
error() { echo "[ERROR] $1"; }
validate_mac() {
echo "$1" | grep -qE "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$"
}
if [ "$(id -u)" -ne 0 ]; then
error "Скрипт должен выполняться от имени root."
exit 1
fi
# === ПРОВЕРКА ПАКЕТОВ ===
info "Проверка необходимых пакетов..."
if opkg list-installed | grep -q "^mosquitto-client-nossl " && opkg list-installed | grep -q "^hostapd-utils "; then
info "Пакеты уже установлены. Пропускаем."
else
info "Установка зависимостей..."
opkg update >/dev/null 2>&1 || warn "Не удалось обновить списки opkg."
opkg install mosquitto-client-nossl hostapd-utils >/dev/null 2>&1 || warn "Не удалось установить пакеты."
if ! opkg list-installed | grep -q "^mosquitto-client-nossl " || ! opkg list-installed | grep -q "^hostapd-utils "; then
warn "Не удалось установить необходимые пакеты."
printf "Продолжить всё равно? [y/N]: "
read answer
case "$answer" in [yY]*) ;; *) exit 1 ;; esac
fi
fi
# === ОПРЕДЕЛЕНИЕ СОСТОЯНИЯ КОНФИГА ===
MQTT_CONFIGURED=false
if [ -f "$CONFIG_FILE" ]; then
if uci -q get openwrt_ha.main.host >/dev/null 2>&1; then
MQTT_CONFIGURED=true
fi
fi
# === МЕНЮ ПРИ НАСТРОЕННОМ MQTT ===
ACTION="install"
if [ "$MQTT_CONFIGURED" = "true" ]; then
CURRENT_HOST=$(uci get openwrt_ha.main.host)
echo ""
echo "Обнаружена конфигурация (MQTT: $CURRENT_HOST)."
echo "1) Обновить скрипты (настройки сохранятся)"
echo "2) Добавить новое устройство"
echo "3) Изменить настройки MQTT"
echo "4) Удалить интеграцию полностью"
echo "5) Выход"
printf "Выберите [1-5]: "
read choice
case "$choice" in
1) ACTION="update" ;;
2) ACTION="add_device" ;;
3) ACTION="change_mqtt" ;;
4) ACTION="uninstall" ;;
5) exit 0 ;;
*) error "Неверный выбор."; exit 1 ;;
esac
fi
# === УДАЛЕНИЕ ===
if [ "$ACTION" = "uninstall" ]; then
info "Удаление интеграции..."
crontab -l 2>/dev/null | grep -v "mqtt_ha_discovery.sh" | crontab - 2>/dev/null || true
/etc/init.d/cron restart 2>/dev/null || true
/etc/init.d/openwrt_presence stop 2>/dev/null || true
/etc/init.d/openwrt_presence disable 2>/dev/null || true
rm -f /etc/init.d/openwrt_presence /etc/hostapd.user /usr/bin/mqtt_ha_discovery.sh "$CONFIG_FILE"
rm -rf "$STATES_DIR"
info "Удаление завершено. Удалите сущности в Home Assistant вручную."
exit 0
fi
# === ВВОД НАСТРОЕК MQTT (только при install/change_mqtt) ===
if [ "$ACTION" = "install" ] || [ "$ACTION" = "change_mqtt" ]; then
echo ""
echo "=== Настройка MQTT брокера ==="
echo "(Нажмите Enter для значения по умолчанию)"
if [ "$MQTT_CONFIGURED" = "true" ] && [ "$ACTION" = "change_mqtt" ]; then
DEFAULT_HOST=$(uci get openwrt_ha.main.host)
DEFAULT_PORT=$(uci get openwrt_ha.main.port)
DEFAULT_USER=$(uci get openwrt_ha.main.user)
DEFAULT_PASS=$(uci get openwrt_ha.main.pass)
DEFAULT_TOPIC=$(uci get openwrt_ha.main.base_topic)
else
DEFAULT_HOST="192.168.1.100"
DEFAULT_PORT="1883"
DEFAULT_USER="mqtt_user"
DEFAULT_PASS="mqtt_password"
DEFAULT_TOPIC="openwrt"
fi
printf "IP или домен MQTT брокера [%s]: " "$DEFAULT_HOST"
read MQTT_HOST
if [ -z "$MQTT_HOST" ]; then MQTT_HOST="$DEFAULT_HOST"; fi
printf "Порт MQTT [%s]: " "$DEFAULT_PORT"
read MQTT_PORT
if [ -z "$MQTT_PORT" ]; then MQTT_PORT="$DEFAULT_PORT"; fi
printf "Логин MQTT [%s]: " "$DEFAULT_USER"
read MQTT_USER
if [ -z "$MQTT_USER" ]; then MQTT_USER="$DEFAULT_USER"; fi
printf "Пароль MQTT [%s]: " "$DEFAULT_PASS"
read MQTT_PASS
if [ -z "$MQTT_PASS" ]; then MQTT_PASS="$DEFAULT_PASS"; fi
printf "Базовый топик MQTT [%s]: " "$DEFAULT_TOPIC"
read BASE_TOPIC
if [ -z "$BASE_TOPIC" ]; then BASE_TOPIC="$DEFAULT_TOPIC"; fi
echo ""
info "Проверка подключения к MQTT..."
if mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USER" -P "$MQTT_PASS" \
-t "${BASE_TOPIC}/test/install" -m "ping" -I "installer_$$" -r 2>/dev/null; then
info "Подключение к MQTT успешно."
else
warn "Не удалось подключиться к MQTT брокеру."
printf "Продолжить всё равно? [y/N]: "
read answer
case "$answer" in [yY]*) ;; *) exit 1 ;; esac
fi
# === СОХРАНЕНИЕ MQTT ЧЕРЕЗ UCI ===
[ -f "$CONFIG_FILE" ] || touch "$CONFIG_FILE"
uci set openwrt_ha.main='mqtt'
uci set openwrt_ha.main.host="$MQTT_HOST"
uci set openwrt_ha.main.port="$MQTT_PORT"
uci set openwrt_ha.main.user="$MQTT_USER"
uci set openwrt_ha.main.pass="$MQTT_PASS"
uci set openwrt_ha.main.base_topic="$BASE_TOPIC"
uci commit openwrt_ha
info "Настройки MQTT сохранены."
fi
# === ДОБАВЛЕНИЕ УСТРОЙСТВ (только при install/add_device) ===
ASK_DEVICES=false
if [ "$ACTION" = "install" ] || [ "$ACTION" = "add_device" ]; then
ASK_DEVICES=true
fi
if [ "$ASK_DEVICES" = "true" ]; then
echo ""
printf "Добавить устройство прямо сейчас? [Y/n]: "
read answer
case "$answer" in [nN]*) ASK_DEVICES=false ;; esac
fi
if [ "$ASK_DEVICES" = "true" ]; then
DEVICE_COUNT=1
while uci -q get "openwrt_ha.device${DEVICE_COUNT}" >/dev/null 2>&1; do
DEVICE_COUNT=$((DEVICE_COUNT + 1))
done
while true; do
echo ""
echo "--- Устройство #$DEVICE_COUNT ---"
printf "Имя устройства (например, 'Телефон'): "
read DEVICE_NAME
if [ -z "$DEVICE_NAME" ]; then DEVICE_NAME="Устройство $DEVICE_COUNT"; fi
while true; do
echo "Введите MAC-адрес(а) через пробел"
echo "Пример: 14:e0:1d:c7:05:76 или 14:e0:1d:c7:05:76 aa:bb:cc:dd:ee:ff"
printf "MAC-адрес(а): "
read DEVICE_MACS
if [ -z "$DEVICE_MACS" ]; then
warn "Необходимо ввести хотя бы один MAC-адрес."
continue
fi
ALL_VALID=true
for mac in $DEVICE_MACS; do
if ! validate_mac "$mac"; then
warn "Неверный формат MAC: $mac"
ALL_VALID=false
break
fi
done
[ "$ALL_VALID" = "true" ] && break
done
echo "Тип устройства:"
echo "1) Трекер (люди, статусы home/not_home)"
echo "2) Тревога/IoT (розетки, статусы online/offline)"
printf "Выберите [1-2] [1]: "
read DEVICE_TYPE_NUM
if [ -z "$DEVICE_TYPE_NUM" ]; then DEVICE_TYPE_NUM="1"; fi
if [ "$DEVICE_TYPE_NUM" = "2" ]; then
DEVICE_TYPE="alarm"
DEFAULT_DELAY="0"
else
DEVICE_TYPE="tracker"
DEFAULT_DELAY="30"
fi
printf "Задержка перед отправкой 'отключен' (сек) [%s]: " "$DEFAULT_DELAY"
read DEVICE_DELAY
if [ -z "$DEVICE_DELAY" ]; then DEVICE_DELAY="$DEFAULT_DELAY"; fi
uci set "openwrt_ha.device${DEVICE_COUNT}"='device'
uci set "openwrt_ha.device${DEVICE_COUNT}.name"="$DEVICE_NAME"
uci set "openwrt_ha.device${DEVICE_COUNT}.macs"="$DEVICE_MACS"
uci set "openwrt_ha.device${DEVICE_COUNT}.type"="$DEVICE_TYPE"
uci set "openwrt_ha.device${DEVICE_COUNT}.delay"="$DEVICE_DELAY"
uci commit openwrt_ha
info "Устройство '$DEVICE_NAME' добавлено."
printf "Добавить еще одно устройство? [Y/n]: "
read answer
case "$answer" in [nN]*) break ;; esac
DEVICE_COUNT=$((DEVICE_COUNT + 1))
done
fi
# === УДАЛЕНИЕ МАРКЕРА ИНИЦИАЛИЗАЦИИ ===
# При любых изменениях нужно переинициализировать состояния
rm -f "$STATES_DIR/.initialized"
info "Маркер инициализации удалён. Состояния будут переинициализированы при следующем запуске."
# === СКАЧИВАНИЕ СКРИПТОВ (только при install/update/change_mqtt) ===
if [ "$ACTION" = "install" ] || [ "$ACTION" = "update" ] || [ "$ACTION" = "change_mqtt" ]; then
info "Загрузка файлов из репозитория..."
if ! wget --spider --no-check-certificate "$GITEA_RAW_URL/hostapd.user" >/dev/null 2>&1; then
error "Не удалось подключиться к репозиторию: $GITEA_RAW_URL"
exit 1
fi
wget --no-check-certificate -O /etc/hostapd.user "$GITEA_RAW_URL/hostapd.user" >/dev/null 2>&1 || exit 1
wget --no-check-certificate -O /usr/bin/mqtt_ha_discovery.sh "$GITEA_RAW_URL/mqtt_ha_discovery.sh" >/dev/null 2>&1 || exit 1
wget --no-check-certificate -O /etc/init.d/openwrt_presence "$GITEA_RAW_URL/openwrt_presence" >/dev/null 2>&1 || exit 1
chmod +x /etc/hostapd.user /usr/bin/mqtt_ha_discovery.sh /etc/init.d/openwrt_presence
fi
# === АВТОЗАПУСК (только при install/update/change_mqtt) ===
if [ "$ACTION" = "install" ] || [ "$ACTION" = "update" ] || [ "$ACTION" = "change_mqtt" ]; then
info "Настройка автозапуска..."
/etc/init.d/openwrt_presence enable >/dev/null 2>&1
/etc/init.d/openwrt_presence restart >/dev/null 2>&1
sleep 2
if ! ps | grep -q "[h]ostapd_cli"; then
warn "Служба запущена, но процесс hostapd_cli не найден."
echo "Проверьте: logread | grep hostapd"
echo "Возможно, ваши интерфейсы Wi-Fi называются не phy0-ap0/phy1-ap0 (проверьте: iw dev)"
fi
# === CRON ===
info "Настройка Cron..."
if command -v crontab >/dev/null 2>&1; then
if ! crontab -l 2>/dev/null | grep -q "mqtt_ha_discovery.sh"; then
(crontab -l 2>/dev/null; echo "* * * * * /usr/bin/mqtt_ha_discovery.sh") | crontab - 2>/dev/null
/etc/init.d/cron restart 2>/dev/null
fi
else
warn "Cron не установлен. Установите: opkg install cron"
fi
fi
# === ПЕРЕЗАПУСК И ИНИЦИАЛИЗАЦИЯ (для всех действий кроме uninstall) ===
info "Применение изменений..."
/etc/init.d/openwrt_presence restart >/dev/null 2>&1
/usr/bin/mqtt_ha_discovery.sh >/dev/null 2>&1 || warn "Discovery завершился с ошибкой."
info "Изменения применены."
echo ""
echo "=================================================="
info "Операция успешно завершена!"
echo "=================================================="
echo "Конфигурация: vi /etc/config/openwrt_ha"
echo "Просмотр: uci show openwrt_ha"
echo "Логи: logread | grep wifi_tracker"
echo ""
echo "Для проверки: выключите Wi-Fi на добавленном устройстве"
echo "и проверьте лог через указанную задержку."