Hospitality / IoT
TV-PORTAL / Damba Relax — Wi-Fi и ТВ-киоск
TV-PORTAL — собственный продакшн-проект для гостевого дома Damba Relax в Янтарном Калининградской области. Гость подтверждает доступ к Wi-Fi звонком, а с телевизора в номере заказывает завтрак, сауну, экскурсии, самокаты, мангал и другие услуги.
Обсудить похожий проект
Задача
Объединить гостевой Wi-Fi, сервисы в номере, оплату, управление персонала и голосовые сценарии в одной надёжной системе.
Решение
Как реализовали проект
Единый Flask-сервис обслуживает гостевой портал, ТВ-интерфейсы всех номеров и административную панель. Он связывает проверку через sms.ru, авторизацию устройств в UniFi, оплату по СБП через ЮKassa, уведомления в Telegram, Home Assistant, Алису и управление Android TV по ADB.
Состав работ
Что вошло в решение
- 01Гостевой Wi-Fi без пароля с проверкой звонком
- 02ТВ-киоск с заказом и оплатой услуг из номера
- 03Единая панель гостей, бронирований, контента и заказов
- 04Оплата по СБП с автоматической сверкой статуса
- 05Голосовой запуск портала через Алису
- 06Мультиномерная архитектура с отдельными темами
Инфраструктура
Архитектура решения
- 01
Один Flask-процесс обслуживает все номера по маршрутам /tv/room-<id>/...
- 02
SQLite хранит гостей, бронирования, заказы, платежи и контент
- 03
Занятость номеров вычисляется по пересечениям бронирований без плотной календарной таблицы
- 04
Фоновый worker сверяет исходящие запросы к ЮKassa без зависимости от входящего webhook
- 05
Caddy выпускает сертификаты через Cloudflare DNS-01 и разделяет гостевой и локальный ТВ-доступ
- 06
Сервис работает в Debian 12 LXC на Proxmox и управляется через systemd
Возможности
Функционал
Подтверждение гостя звонком
Портал запускает серверную проверку номера через sms.ru. Процесс продолжается даже после закрытия captive-браузера iOS при переходе в приложение телефона.
Доступ к Wi-Fi через UniFi
После успешной проверки сервис находит устройство по MAC-адресу и выдаёт ему доступ через UniFi API без общего пароля для гостей.
Заказ услуг с телевизора
Крупный интерфейс ТВ-киоска позволяет заказать завтрак, сауну, экскурсию, самокаты, мангал и дополнительные услуги прямо из номера.
Оплата по СБП
ЮKassa формирует QR-код, а фоновая сверка подтверждает фактический статус платежа. Заказ не становится оплаченным без ответа платёжной системы.
Панель персонала
Сотрудники управляют гостями, бронированиями, номерами, контентом и заказами в одном интерфейсе и получают оперативные уведомления.
Голосовые сценарии
Команда Алисе запускает сценарий Home Assistant: телевизор просыпается, а ADB открывает страницу портала конкретного номера.
Управление несколькими номерами
Новый номер добавляется через конфигурацию и получает собственный маршрут и тему без развёртывания отдельного приложения.
Уведомления и контроль состояния
Telegram Bot API сообщает персоналу о событиях, а endpoint /health используется для мониторинга доступности сервиса.
Стек проекта
Технологии
Защита данных
Безопасность
- Параметризованные SQL-запросы и ручные транзакции при миграциях
- HMAC-сессия администратора и отдельный X-Admin-Key для API
- X-Frame-Options: DENY и no-store для административных страниц
- Проверка IP ЮKassa и Idempotence-Key для платёжных операций
- Резервная копия приложения и рабочей SQLite-базы перед рискованным деплоем
Живые данные
Интеграции
UX / UI
Дизайн-процесс
Интерфейс проектировался прежде всего для телевизора: крупные зоны нажатия, короткие сценарии, высокая контрастность и отдельная тема каждого номера. Панель персонала отделена от гостевого контура, а содержимое услуг меняется централизованно.
Инженерная работа
Нетривиальные решения
Платежи без публичного webhook
Сервис не открыт входящим трафиком из интернета, поэтому статус платежа подтверждает исходящий reconcile-worker. Webhook оставлен как будущее улучшение, но не является точкой отказа.
Проверка после закрытия captive-браузера
iOS закрывает captive-окно при переходе по tel:. Проверку перенесли в серверный worker, который завершает сценарий независимо от состояния браузера.
Несколько номеров в одном процессе
Маршруты, темы и сервисы номера вынесены в конфигурацию, поэтому новые комнаты подключаются без копирования приложения и отдельных баз.
Голосовое управление телевизором
Home Assistant принимает триггер Алисы и через ADB будит нужный Android TV, после чего открывает персональный адрес комнаты.
Безопасные миграции живой базы
Миграции сначала прогоняются на копии продакшн-базы. Так была обнаружена зависимость SELECT * от физического порядка колонок и устранена до выкладки.
Честные границы продакшна
Текущий браузерный киоск работает в продакшне. Нативный Kotlin-клиент ещё развивается, а переход с Flask dev server на production WSGI зафиксирован как следующий инфраструктурный этап.
Результат
Система работает в реальном гостевом доме: выдаёт доступ к Wi-Fi, принимает заказы и оплату, уведомляет персонал и управляет ТВ-сценариями. Нативный клиент для Android TV развивается отдельно; текущая продакшн-версия использует браузерный киоск и ADB.
Следующий кейс