294 lines
12 KiB
Bash
294 lines
12 KiB
Bash
#!/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 "и проверьте лог через указанную задержку." |