Перейти к содержимому

Настройка

Sendspin Bluetooth Bridge хранит постоянные настройки в config.json внутри директории /config. Управлять этими значениями можно через веб-интерфейс, через вкладку настройки аддона Home Assistant или напрямую через файл.

Есть два основных способа управлять настройками:

ПоверхностьДля чего подходитЧто важно
Веб-интерфейсЕжедневное управление устройствами, адаптерами, auth и runtime-поведениемРаботает для Docker, LXC и аддона
Configuration таб аддона HASupervisor-managed параметры аддонаУдобен для HA-native редактирования

Общий вид обновлённого раздела Configuration

Новый раздел конфигурации разбит на пять вкладок вместо одной длинной формы.

ВкладкаЧто в ней находится
GeneralИмя bridge, timezone, latency, web/UI-порты, smooth restart, update policy
DevicesТаблица колонок, сканирование, импорт paired-устройств
BluetoothИмена адаптеров, reconnect policy, codec preference
Music AssistantToken flows, endpoint MA, monitor, routing toggles
SecurityLocal auth, session timeout, защита от перебора

General содержит настройки всего экземпляра bridge:

  • Bridge name — добавляется к именам плееров как Player @ Name.
  • Timezone — с live preview текущего времени.
  • PulseAudio latency (ms) — больше значение = выше устойчивость на слабом железе.
  • Web UI port — порт прямого доступа в браузере для Docker / LXC / systemd. Игнорируется в режиме HA addon: Supervisor назначает ingress-порт динамически.
  • Base player listen port — стартовый порт для автоматически назначаемых sendspin listener’ов устройств.
  • Smooth restart — mute перед перезапуском и показ прогресса.
  • Check for updates / Auto-update — доступны вне режима HA addon.

Если оставить поля портов пустыми, standalone-режим использует 8080 для web UI и 8928 для listener’ов плееров. В режиме Home Assistant addon все три канала (stable / rc / beta) поставляются с ingress_port: 0, поэтому Supervisor назначает свободный порт во время запуска — это изменение появилось в v2.55.0, чтобы варианты аддона перестали конфликтовать с Matter / Thread и другими addons на host-network. Per-channel дефолты для базового listener-порта (8928 / 9028 / 9128) сохраняются — они нужны, чтобы listener’ы устройств не пересекались, когда несколько вариантов аддона работают одновременно. WEB_PORT, заданный внутри аддона, игнорируется; UI открывается из боковой панели Home Assistant.

Вкладка Devices с таблицей fleet и discovery workflow

Devices разделена на две роли:

  • Device fleet — основная таблица повседневных изменений.
  • Discovery & import — поиск nearby speakers и импорт уже спаренных устройств.

Каждая строка устройства хранит:

ПолеДля чего нужно
EnabledВременно исключить устройство из старта
Player nameИмя в Music Assistant
MACBluetooth-адрес колонки
AdapterПривязка к конкретному контроллеру
PortОпциональный listen_port; иначе bridge использует BASE_LISTEN_PORT + индекс устройства
Delaystatic_delay_ms — компенсация hw-задержки за sink’ом (0–5 000 мс, дефолт 300 для новых устройств)
LiveRuntime badge вроде Playing, Connected, Released или Not seen

В advanced-части строки доступны:

  • Preferred format вроде flac:44100:16:2.
  • Listen host (listen_host) для переопределения advertised-адреса устройства.
  • Keepalive interval (keepalive_interval) для колонок, которые слишком быстро уходят в сон.

Текущее runtime-поведение завязано на интервале: любой положительный keepalive_interval включает keepalive-тишину, значения меньше 30 секунд поднимаются до 30, а 0 или пустое поле keepalive выключают. В старых конфигурациях Home Assistant addon ещё может встречаться legacy-флаг keepalive_silence, но актуальное поведение bridge определяется через keepalive_interval > 0.

Вкладка Bluetooth с inventory адаптеров и recovery policy

Bluetooth объединяет inventory и политику восстановления:

  • Понятные имена адаптеров для dashboard.
  • Ручные записи адаптеров, если автоопределение неполное.
  • Refresh detection.
  • Настройку BT check interval.
  • Настройку Auto-disable threshold. При достижении порога устройство сохраняется как disabled, пока вы не включите его снова.
  • Переключатель Prefer SBC codec.

Карточка Connection status в Music Assistant с действием Reconfigure и текущим состоянием интеграции

Вкладка Music Assistant с token actions и bridge integration settings

Music Assistant объединяет состояние соединения и auth helper’ы:

  • summary Connection status,
  • действие Reconfigure прямо в карточке статуса соединения — основной способ осознанно переоткрыть auth-flow после первичной настройки,
  • Discover для поиска сервера или повторного использования уже известного URL,
  • Get token с логином/паролем MA. При успехе bridge сохраняет MA_API_URL, long-lived MA_API_TOKEN и MA_USERNAME, но не сохраняет пароль,
  • fallback через Home Assistant OAuth / MFA, если экземпляр MA работает поверх HA и прямой логин MA этого требует,
  • Get token automatically для HA-backed MA. Этот helper показывается только в addon/Ingress-режиме, потому что silent bootstrap токена зависит от живой browser-session Home Assistant. В HA Ingress UI сначала пробует silent auth через текущий HA browser token, а затем при необходимости переходит к popup-flow,
  • ручное поле MA API token,
  • поля MA server и MA WebSocket port,
  • переключатели WebSocket monitor, Route volume through MA, Route mute through MA.

Когда bridge уже подключён, auth controls убираются с глаз до тех пор, пока вы не нажмёте Reconfigure или не попадёте сюда по guidance-CTA, который явно просит обновить токен.

В standalone-режиме вкладка Security управляет локальным доступом к веб-интерфейсу:

  • Enable web UI authentication,
  • Session timeout (1–168 часов),
  • Brute-force protection,
  • поля Max attempts, Window и Lockout,
  • flow Set password.

Standalone-login использует CSRF-защищённые формы и cookie с SameSite=Lax + HttpOnly. В режиме Home Assistant addon доступ всегда контролирует сам HA / Ingress, поэтому standalone-контролы скрываются.

Нижняя панель общая для всех вкладок:

  • Save записывает config.json.
  • Save & Restart сохраняет и сразу перезапускает сервис. Используйте это для изменений портов, auth/session-настроек и любых параметров, применяемых на старте.
  • Cancel восстанавливает последние сохранённые значения формы.
  • Download экспортирует share-safe JSON-файл с timestamp и без секретов вроде MA_API_TOKEN, password hash и secret key.
  • Upload импортирует ранее сохранённый config и сохраняет существующие password hash, secret key и MA token на стороне сервера.

Панель Configuration аддона HA с core options

В режиме аддона Home Assistant Supervisor показывает собственную вкладку Configuration.

Откройте Настройки → Аддоны → Sendspin Bluetooth Bridge → Configuration.

Основные поля аддона:

ПараметрНазначение
sendspin_serverХост/IP Music Assistant (без префикса схемы, без порта, без пути — просто 192.168.1.11 или ma.local), или auto для mDNS
sendspin_portПорт Sendspin WebSocket — по умолчанию 8927, совпадает с дефолтом провайдера Sendspin в Music Assistant. Старые конфиги с 9000 продолжают работать: бридж пробует настроенный порт и автоматически переключается, если он закрыт
web_portЧитается, но не применяется в режиме аддона: Supervisor назначает ingress-порт динамически. Поле оставлено в схеме ради совместимости — можно оставить пустым.
base_listen_portСтартовый порт для автоматически назначаемых listener’ов устройств
bridge_nameНеобязательная метка экземпляра bridge
tzЧасовой пояс IANA
pulse_latency_msecПодсказка размера аудиобуфера
prefer_sbc_codecПредпочтение более лёгкого кодека
bt_check_intervalИнтервал polling-проверки
bt_max_reconnect_failsПорог auto-disable
auth_enabledStandalone-style auth toggle для прямого доступа; в HA addon mode auth всё равно принудительно контролируется HA
ma_api_url / ma_api_tokenREST-интеграция с Music Assistant
ma_auto_silent_authРазрешить addon/Ingress-страницам пробовать silent-создание HA-backed MA-токена при открытии
volume_via_ma / mute_via_maМаршрутизация управления через MA
update_channelВыбор release-lane для in-app update checks и предупреждений
log_levelБазовый уровень логирования

Списки устройств и адаптеров аддона HA вместе с диалогом редактирования устройства

Диалог редактирования устройства в конфигурации аддона HA

Через addon form доступны и полные структуры Bluetooth devices и Bluetooth adapters. Старые addon-конфиги могут по-прежнему сохранять legacy-поле keepalive_silence при трансляции, но текущее runtime-поведение определяется через keepalive_interval.

Что важно для addon-режима:

  • auth в Home Assistant / Ingress всегда принудительно включена;
  • пользовательский web_port в addon-режиме игнорируется — Supervisor назначает ingress-порт динамически (ingress_port: 0); параллельный прямой listener bridge сейчас не открывает;
  • silent bootstrap токена HA для Music Assistant доступен только при открытом UI через аутентифицированную HA/Ingress browser-session.

Bridge поддерживает два необязательных top-level override-поля:

КлючК чему применяетсяЗначение по умолчаниюЧто важно
WEB_PORTlistener веб-интерфейса8080 вне HA addon modeИгнорируется в режиме HA addon. Supervisor назначает ingress-порт динамически (в манифесте аддона стоит ingress_port: 0), фиксированного addon-порта, который можно было бы переопределить через WEB_PORT, больше нет. UI открывается через сайдбар Home Assistant.
BASE_LISTEN_PORTавтоматически назначаемые per-device Sendspin listener’ы8928 вне HA addon modeСтартовый порт, если устройство не задаёт собственный listen_port. Учитывается во всех runtime-режимах, включая HA addon.

В Home Assistant addon mode listener-диапазоны специально разведены по каналам, чтобы несколько вариантов аддона могли уживаться на одном HAOS-хосте, не конфликтуя по per-device listener-портам:

Установленный трек аддонаChannel base listen portChannel web-port fallback
Stable89288080
RC90288081
Beta91288082

Колонка base listen port — это активный дефолт для канала, он напрямую виден в URL listener’ов устройств. Колонка web-port fallback — резервное значение, используемое только в случае, если bridge не смог обратиться к /addons/self/info Supervisor REST API за динамически назначенным ingress-портом. В обычной работе пользователь эти числа не увидит — Supervisor возвращает свой runtime-порт, и UI отдаётся на нём.

Используйте overrides только когда нужно:

  • нестандартный web-порт для Docker / LXC / systemd (HA addon mode сейчас не поддерживает прямой не-Ingress listener — WEB_PORT читается, но не применяется);
  • иной стартовый диапазон device-listener’ов на том же хосте (например, два non-addon bridge-экземпляра).

Каждое Bluetooth-устройство может также задавать собственные listen_host и listen_port.

Используйте device-level overrides, если:

  • конкретной колонке нужен стабильный известный порт;
  • вы делите устройства между несколькими bridge-экземплярами и хотите явный план портов;
  • нужно убрать коллизию, не двигая весь базовый диапазон bridge.
КлючТипОписание
SENDSPIN_SERVERstringХост Music Assistant или auto
SENDSPIN_PORTintegerПорт Sendspin WebSocket
WEB_PORTinteger или nullOverride прямого web-порта
BASE_LISTEN_PORTinteger или nullНеобязательный base port для автоматически назначаемых listener’ов устройств
BRIDGE_NAMEstringНеобязательная метка экземпляра
TZstringЧасовой пояс IANA
PULSE_LATENCY_MSECintegerПодсказка аудиобуфера
BT_CHECK_INTERVALintegerИнтервал проверки Bluetooth
BT_MAX_RECONNECT_FAILSintegerПорог auto-disable; 0 — без ограничений
BT_CHURN_THRESHOLDintegerПорог изоляции частых переподключений; 0 отключает
BT_CHURN_WINDOWnumberОкно времени в секундах для обнаружения churn (по умолчанию 300)
PREFER_SBC_CODECbooleanПредпочтение кодека с меньшей нагрузкой
DISABLE_PA_RESCUE_STREAMSbooleanВыгрузить PulseAudio module-rescue-streams при старте, чтобы предотвратить смещение sink при переподключении
DUPLICATE_DEVICE_CHECKbooleanОбнаружение дублирующихся устройств между bridge-экземплярами
AUTH_ENABLEDbooleanВключить локальную auth-защиту вне HA addon mode; в HA addon mode auth всегда принудительно включена
SESSION_TIMEOUT_HOURSintegerСрок жизни browser-сессии
BRUTE_FORCE_PROTECTIONbooleanВключить временную блокировку после неудачных входов
BRUTE_FORCE_MAX_ATTEMPTSintegerМаксимум попыток в окне
BRUTE_FORCE_WINDOW_MINUTESintegerRolling window для неудачных входов
BRUTE_FORCE_LOCKOUT_MINUTESintegerДлительность блокировки
MA_API_URLstringURL REST API Music Assistant
MA_API_TOKENstringТокен Music Assistant API
MA_USERNAMEstringUsername, использованный при последнем успешном MA login-flow
MA_AUTO_SILENT_AUTHbooleanРазрешить addon/Ingress-страницам пробовать silent-создание HA-backed MA-токена при открытии
MA_WEBSOCKET_MONITORbooleanLive monitor now-playing и очереди
VOLUME_VIA_MAbooleanПропускать volume через MA
MUTE_VIA_MAbooleanПропускать mute через MA
SMOOTH_RESTARTbooleanMute перед перезапуском и показ прогресса
UPDATE_CHANNELstringКанал обновлений: stable, rc или beta
AUTO_UPDATEbooleanРазрешить auto-update там, где он поддерживается
CHECK_UPDATESbooleanВключить проверку обновлений
LOG_LEVELstringБазовый уровень логирования: DEBUG, INFO, WARNING, ERROR
HA_AREA_NAME_ASSIST_ENABLEDbooleanАвтоматическое определение имён зон Home Assistant для адаптеров
STARTUP_BANNER_GRACE_SECONDSintegerСекунды до появления баннера запуска (0–300)
RECOVERY_BANNER_GRACE_SECONDSintegerСекунды до появления баннеров восстановления/ошибок (0–300)
TRUSTED_PROXIESarrayДополнительные proxy IP, которым разрешено передавать trusted Ingress headers

Следующие ключи записываются bridge во время работы и обычно не требуют ручного редактирования:

КлючТипОписание
CONFIG_SCHEMA_VERSIONintegerВнутренняя версия схемы для миграций конфига
AUTH_PASSWORD_HASHstringPBKDF2-SHA256 хеш пароля веб-интерфейса
SECRET_KEYstringКлюч шифрования сессий Flask; генерируется автоматически при первом запуске
LAST_VOLUMESobjectСохранённая громкость устройств (MAC → integer)
LAST_SINKSobjectСохранённое имя PulseAudio-sink устройства (MAC → string)
MA_AUTH_PROVIDERstringПровайдер авторизации текущего подключения к MA ("ha" и т.д.)
MA_TOKEN_INSTANCE_HOSTNAMEstringHostname экземпляра MA, выдавшего токен
MA_TOKEN_LABELstringПонятная метка сохранённого MA-токена
MA_ACCESS_TOKENstringТекущий OAuth access token MA
MA_REFRESH_TOKENstringOAuth refresh token MA для автоматического обновления
HA_ADAPTER_AREA_MAPobjectПривязка MAC адаптера → зона Home Assistant

Чувствительные поля: AUTH_PASSWORD_HASH, SECRET_KEY, MA_ACCESS_TOKEN и MA_REFRESH_TOKEN удаляются из скачиваемого конфига. Upload сохраняет серверные значения этих ключей.

{
"BLUETOOTH_DEVICES": [
{
"mac": "AA:BB:CC:DD:EE:FF",
"player_name": "Колонка в гостиной",
"adapter": "hci0",
"static_delay_ms": 300,
"listen_host": "0.0.0.0",
"listen_port": 8928,
"preferred_format": "flac:44100:16:2",
"keepalive_interval": 60,
"enabled": true
}
]
}
ПолеОписание
macBluetooth MAC колонки
player_nameИмя в Music Assistant
adapterID или MAC адаптера
static_delay_msДекларирует hw-задержку, которую колонка добавляет за sink’ом, в мс (0–5 000). Sendspin-клиент вычитает это значение из времени проигрывания каждого чанка, поэтому аудио выходит на железо раньше ровно на эту величину и приходит на запланированный таймштамп после того, как железо добавит свою реальную задержку. Дефолт для новых устройств — 300; увеличивайте для колонок, которые стабильно отстают от группы, уменьшайте — для тех, что опережают. См. Delay tuning и keepalive и Измерение латентности каждой колонки через MassDroid.
listen_hostПереопределение advertised host для listener’а этого устройства
listen_portПользовательский порт listener’а; если не задан, runtime использует BASE_LISTEN_PORT + индекс устройства
preferred_formatПредпочтительный аудиоформат
keepalive_silenceLegacy-совместимый флаг из старых addon-конфигов; отдельного переключателя для него в текущем web UI нет
keepalive_intervalИнтервал keepalive-тишины в секундах; любое положительное значение включает keepalive, минимальный эффективный интервал — 30 секунд
room_idID зоны / комнаты Home Assistant для устройства
room_nameПонятное имя комнаты
idle_disconnect_minutesОтключить Bluetooth после указанного числа минут бездействия; 0 отключает
enabledПри false устройство пропускается на старте

Каждый эффективный listen_port должен быть уникальным для устройства. Если на одном хосте работает несколько bridge-экземпляров, задайте им разные диапазоны BASE_LISTEN_PORT или явные listen_port для каждого устройства.

{
"BLUETOOTH_ADAPTERS": [
{
"id": "hci0",
"mac": "C0:FB:F9:62:D6:9D",
"name": "Адаптер в гостиной"
}
]
}
ПолеОписание
idИмя интерфейса, например hci0
macMAC-адрес адаптера
nameПонятная метка в UI
  • HA Ingress использует динамически назначаемый Home Assistant Supervisor порт (ingress_port: 0 в манифесте аддона). WEB_PORT, заданный внутри аддона, не переопределяет ingress и не открывает параллельный прямой listener.
  • Multi-bridge setups вне HA addon mode должны использовать непересекающиеся диапазоны WEB_PORT и BASE_LISTEN_PORT. Несколько вариантов аддона на одном HAOS-хосте уже получают разные дефолты BASE_LISTEN_PORT по каналам (8928 / 9028 / 9128) — listener’ы устройств не пересекаются автоматически.
  • Per-device overrides важнее: listen_port и listen_host перекрывают top-level defaults.
  • Конфликт портов критичен для daemon: дублирующиеся listen_port не дадут listener’у устройства забиндиться.

Bridge читает переменные окружения при запуске. Они делятся на три группы: bootstrap-переменные, которые вы задаёте сами, контейнерные внутренности, устанавливаемые entrypoint.sh, и переменные аддона Home Assistant, внедряемые Supervisor.

Наиболее часто используемые overrides. CONFIG_DIR всегда определяет, где находится config.json, а env-override для WEB_PORT / BASE_LISTEN_PORT разрешаются раньше сохранённых значений конфига.

ПеременнаяПо умолчаниюОписание
CONFIG_DIR/configПуть к директории конфига
WEB_PORT8080 (standalone)Override прямого web UI порта для Docker / LXC / systemd. Игнорируется в HA addon mode — Supervisor назначает ingress-порт динамически, параллельного прямого listener’а bridge не открывает.
BASE_LISTEN_PORT8928 (standalone)Стартовый порт для auto-assigned player listeners. В HA addon mode per-channel дефолты: stable 8928, rc 9028, beta 9128 (чтобы варианты аддона не конфликтовали).
TZиз конфигаOverride часового пояса, используемый при инициализации локального времени runtime
BRIDGE_NAMEиз конфигаНеобязательный override имени bridge до появления сохранённого имени
LOG_LEVELINFOУровень логирования: DEBUG, INFO, WARNING, ERROR. Также задаётся через конфиг или веб-интерфейс
WEB_THREADS8Количество HTTP-потоков Waitress; увеличьте до 16 для 20+ устройств
DEMO_MODE(не задана)Установите 1, true или yes для запуска в демо/эмуляционном режиме без реального Bluetooth-оборудования
SENDSPIN_NAMESendspin-{hostname}Override префикса имени плеера по умолчанию
SENDSPIN_STATIC_DELAY_MS0Глобальный override статической задержки звука в миллисекундах (0–5 000). Значения вне диапазона клампятся; отрицательные значения в sendspin 7.0+ больше не принимаются.

Устанавливаются автоматически entrypoint.sh при запуске контейнера. Ручная настройка требуется редко.

ПеременнаяПо умолчаниюОписание
PULSE_SERVER(автоопределение)Путь к сокету PulseAudio / PipeWire (например, unix:/run/audio/pulse.sock)
PULSE_LATENCY_MSECиз конфига (600)Подсказка задержки PulseAudio в миллисекундах; берётся из ключа конфига PULSE_LATENCY_MSEC
PULSE_SINK(на подпроцесс)PulseAudio-sink по умолчанию; задаётся отдельно для каждого подпроцесса устройства для маршрутизации звука на нужную колонку
AUDIO_UID1000User ID для доступа к сокету PulseAudio
AUDIO_GID(из сокета)Group ID для доступа к сокету PulseAudio
DBUS_SYSTEM_BUS_ADDRESS(автоопределение)Путь к системному сокету D-Bus
STARTUP_DEPENDENCY_WAIT_ATTEMPTS45Максимальное число попыток ожидания D-Bus, Bluetooth и аудио при старте
STARTUP_DEPENDENCY_WAIT_DELAY_SECONDS1Задержка в секундах между проверками зависимостей при старте

Внедряются HA Supervisor; с точки зрения bridge — только для чтения.

ПеременнаяПо умолчаниюОписание
SUPERVISOR_TOKEN(только HA)Токен API Home Assistant Supervisor; его наличие активирует addon-режим
HA_CORE_URLhttp://homeassistant:8123URL Home Assistant Core для auth-flow и API-вызовов
HOSTNAME(системный)Hostname контейнера; используется для определения типа аддона
SENDSPIN_HA_OPTIONS_FILE/data/options.jsonПуть к файлу опций аддона, записанному Supervisor
SENDSPIN_HA_CONFIG_FILE/data/config.jsonПуть к транслированному конфигу, используемому в addon-режиме