连接与配网

CONNECTION

Music Assistant / Home Assistant 连接操作手册

版本: v1.9-ma-ha 日期: 2026-08-25 适用设备: KABU Speaker (ESP32-S3)

本文档详细记录 Music Assistant (MA) 和 Home Assistant (HA) 与 KABU 设备的连接过程,作为标准操作手册使用。


目录

  1. 前置准备
  2. Music Assistant 连接 Sendspin 播放器
  3. Home Assistant 连接 DLNA 渲染器
  4. 设备模式切换
  5. 排错指南
  6. 技术参考

1. 前置准备

1.1 环境要求

组件版本/要求说明
Docker Desktop4.87.0+数据盘迁移至 E:\docker-data
Music Assistant2.9.13aiosendspin 必须 6.0.5
Home Assistantstable内部 URL 必须配置为宿主机 LAN IP
KABU 固件v1.9-ma-ha支持 legacy 明文方言自动协商
网络同一局域网设备与宿主机互通

1.2 端口映射(docker-compose.yml)

services:
  homeassistant:
    image: ghcr.io/home-assistant/home-assistant:stable
    ports:
      - "8123:8123"   # Web UI / API
      - "14000:14000" # DLNA GENA 事件回调(必需)
    volumes:
      - ./home-assistant:/config

  musicassistant:
    image: ghcr.io/music-assistant/server:latest
    ports:
      - "8095:8095"   # Web UI / API
    volumes:
      - ./music-assistant:/data
      - ./music:/music

1.3 启动服务

cd E:\ha-ma-env
docker compose up -d
docker compose ps

验证访问:


2. Music Assistant 连接 Sendspin 播放器

2.1 设备端准备

步骤 1: 切换设备到 sendspin 模式
# 查询当前模式
curl -s http://<设备IP>/api/device/mode | jq '.mode, .boot_profile'

# 切换到 sendspin 模式(设备会重启)
curl -X POST http://<设备IP>/api/device/mode \
  -H "Content-Type: application/json" \
  -d '{"mode":"sendspin"}'

等待 30-60 秒设备重启完成。

步骤 2: 验证设备状态
# 检查设备模式
curl -s http://<设备IP>/api/device/mode | jq '.mode, .phase'
# 期望输出: "sendspin", "active"

# 检查 Sendspin 播放器状态
curl -s http://<设备IP>/api/sendspin/player | jq '.server_connected, .time_synced, .stream_active'
# 初始状态: false, false, false
步骤 3: 确认 mDNS 广播(可选)
# 在宿主机执行(需要 python-zeroconf)
python -c "from zeroconf import Zeroconf, ServiceBrowser; import time, socket
class L:
    def add_service(self, z, t, n):
        i = z.get_service_info(t, n)
        if i and '_sendspin' in t:
            print(f'Found: {n} at {[socket.inet_ntoa(a) for a in i.addresses]}:{i.port}')
    def remove_service(self,*a): pass
    def update_service(self,*a): pass
z = Zeroconf()
b = ServiceBrowser(z, '_sendspin._tcp.local.', L())
time.sleep(5)
z.close()"

期望输出:

Found: 3CDC75F8E1F8@KABU._sendspin._tcp.local. at ['192.168.1.67']:8928

2.2 MA 端配置

步骤 4: 添加 Sendspin 播放器(手动 IP)
  1. 打开 MA Web UI: <http://localhost:8095>
  2. 进入 Settings → Players
  3. 点击 + Add player manually
  4. 输入设备 IP(如 192.168.1.67)
  5. 点击 Save
注意: 容器内 mDNS 不可用(Windows 10 无 mirrored 网络),必须手动添加。
步骤 5: 等待自动连接

MA 会自动尝试连接设备,过程如下:

第一次连接尝试(spec 模式):

第二次连接尝试(spec 模式):

第三次连接尝试(legacy 模式,自动激活):

步骤 6: 验证连接状态

检查 MA 日志:

docker logs musicassistant --tail 50 | grep -i "sendspin\|kabu"

期望输出:

Player (type protocol) registered: M2m1UBZEY0WOY7_.../KABU
Creating universal player upm2m1ubzey0woy7_gacblzcjlzckbjf5ub_pamt7uwsg with protocol players: ['M2m1UBZEY0WOY7_GAcbLZCJLZCKbjf5uB_pAMt7uWSg']

检查设备状态:

curl -s http://<设备IP>/api/sendspin/player | jq '.'

期望输出:

{
  "role": "member",
  "server_connected": true,
  "time_synced": true,
  "stream_active": false,
  "server_name": "Music Assistant",
  "session_owner": "music_assistant_external",
  "volume": 50,
  "muted": false,
  "sample_rate": 48000,
  "chunks_received": 0,
  "chunks_dropped_late": 0,
  "underruns": 0
}

关键指标:

2.3 播放测试

步骤 7: 添加音乐源
  1. MA Web UI → Settings → Providers
  2. 点击 + Add provider
  3. 选择 Local Files
  4. 配置路径: /music
  5. 点击 Save

将音频文件放入 E:\ha-ma-env\music\ 目录。

步骤 8: 播放音频
  1. MA Web UI → Music Library
  2. 选择本地文件(如 kabu_test_tone.wav)
  3. 点击播放按钮
  4. 选择输出设备: KABU
步骤 9: 验证播放状态

MA 端:

设备端:

curl -s http://<设备IP>/api/sendspin/player | jq '.stream_active, .chunks_received, .underruns'

期望输出:

true
2849
0

音频输出:设备应播放音乐,可通过 DAC 听到声音。

步骤 10: 控制测试

暂停/恢复:

音量调节:

# 查看当前音量
curl -s http://<设备IP>/api/sendspin/player | jq '.volume'

# MA 调节音量到 30
# 验证设备音量同步
curl -s http://<设备IP>/api/sendspin/player | jq '.volume'
# 期望输出: 30

3. Home Assistant 连接 DLNA 渲染器

3.1 设备端准备

步骤 1: 切换设备到 dlna 模式
# 切换到 dlna 模式(设备会重启)
curl -X POST http://<设备IP>/api/device/mode \
  -H "Content-Type: application/json" \
  -d '{"mode":"dlna"}'

等待 30-60 秒设备重启完成。

步骤 2: 验证 DLNA 服务
# 检查设备模式
curl -s http://<设备IP>/api/device/mode | jq '.mode, .phase'
# 期望输出: "dlna", "active"

# 获取 DLNA 设备描述
curl -s http://<设备IP>:49152/rootDesc.xml | head -20

期望输出(XML 格式):

<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
  <specVersion><major>1</major><minor>0</minor></specVersion>
  <device>
    <deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
    <friendlyName>KABU</friendlyName>
    <manufacturer>KABU</manufacturer>
    <modelName>KABU</modelName>
    <modelNumber>1.9</modelNumber>
    ...
  </device>
</root>

3.2 HA 端配置

步骤 3: 配置 HA 内部 URL
  1. 打开 HA Web UI: <http://localhost:8123>
  2. 进入 Settings → System → Network
  3. 找到 Home Assistant URL
  4. 设置 Internal URL: http://192.168.1.32:8123(替换为你的宿主机 LAN IP)
  5. 点击 Save
重要: 必须配置为宿主机 LAN IP,否则设备无法访问 HA 媒体文件。
步骤 4: 添加 DLNA Digital Media Renderer 集成
  1. 进入 Settings → Devices & Services
  2. 点击 + ADD INTEGRATION
  3. 搜索 DLNA Digital Media Renderer
  4. 选择 Manual configuration
  5. 输入 URL: http://<设备IP>:49152/rootDesc.xml
  6. 点击 Submit

等待 HA 发现设备并创建 media_player.kabu 实体。

步骤 5: 配置 DLNA 集成选项(必需)
  1. 进入 Settings → Devices & Services → DLNA Digital Media Renderer
  2. 找到 KABU 设备
  3. 点击 CONFIGURE(齿轮图标)
  4. 设置以下选项:
选项值说明
Listen port14000容器发布的端口
Callback URL overridehttp://192.168.1.32:14000/notify宿主机 LAN IP + 端口
  1. 点击 Save
关键: 不配置回调会导致 pause/stop 功能缺失、音量状态不更新。
步骤 6: 验证集成
  1. 进入 Settings → Devices & Services → DLNA Digital Media Renderer → KABU
  2. 查看设备信息:
  1. 进入 Developer Tools → States
  2. 搜索 media_player.kabu
  3. 查看属性:
   friendly_name: KABU
   supported_features: 135693  # 包含 PAUSE (1)
   volume_level: 0.5
   is_volume_muted: false

3.3 播放测试

步骤 7: 准备媒体文件

将音频文件放入 E:\ha-ma-env\home-assistant\media\ 目录。

例如:kabu_test_tone.wav(30 秒 44.1kHz 正弦波)

步骤 8: 通过 Developer Tools 播放
  1. 进入 Developer Tools → Services
  2. 选择服务: media_player.play_media
  3. 填写参数:
   entity_id: media_player.kabu
   media_content_id: media-source://media_source/local/kabu_test_tone.wav
   media_content_type: music
  1. 点击 CALL SERVICE
步骤 9: 验证播放状态

HA 端:

  1. 进入 Developer Tools → States
  2. 搜索 media_player.kabu
  3. 查看状态:
   state: playing
   attributes:
     media_content_id: http://192.168.1.32:8123/media/local/kabu_test_tone.wav?authSig=...
     media_content_type: music
     media_title: Home Assistant
     media_position: 15  # 当前播放位置(秒)
     volume_level: 0.5

设备端:

控制测试:

暂停:

# Developer Tools → Services
Service: media_player.media_pause
entity_id: media_player.kabu

验证:

恢复:

Service: media_player.media_play
entity_id: media_player.kabu

验证:

音量调节:

Service: media_player.volume_set
entity_id: media_player.kabu
volume_level: 0.3

验证:

停止:

Service: media_player.media_stop
entity_id: media_player.kabu

验证:

3.4 GENA 事件验证(高级)

如需验证 DLNA 事件订阅正常工作:

# 在宿主机启动 GENA 探针(已提供 gena_probe.py)
python E:\ha-ma-env\gena_probe.py

期望输出:

SUBSCRIBE: 200 uuid:... Second-300
SetAVTransportURI -> 200
Play -> 200
Stop -> 200
NOTIFY from ('<设备IP>', <port>)
...
TOTAL_NOTIFIES: 3

4. 设备模式切换

4.1 模式说明

模式用途适用场景
sendspinMusic Assistant 播放器MA 投送音乐
dlnaHome Assistant DLNA 渲染器HA 投送音乐
airplayAirPlay 接收器iPhone/Mac 投送
radio网络收音机独立播放

4.2 切换命令

# 查询当前模式
curl -s http://<设备IP>/api/device/mode | jq '.mode, .boot_profile'

# 切换到指定模式(设备会重启)
curl -X POST http://<设备IP>/api/device/mode \
  -H "Content-Type: application/json" \
  -d '{"mode":"<mode>"}'

示例:

# 切换到 sendspin 模式(用于 MA)
curl -X POST http://192.168.1.67/api/device/mode \
  -H "Content-Type: application/json" \
  -d '{"mode":"sendspin"}'

# 切换到 dlna 模式(用于 HA)
curl -X POST http://192.168.1.67/api/device/mode \
  -H "Content-Type: application/json" \
  -d '{"mode":"dlna"}'

4.3 重启等待

设备切换模式后会重启,需要等待:

  # 循环检查直到 phase 变为 active
  while true; do
    phase=$(curl -s http://<设备IP>/api/device/mode | jq -r '.phase')
    if [ "$phase" = "active" ]; then
      echo "Device ready"
      break
    fi
    sleep 5
  done

5. 排错指南

5.1 MA 连接失败

问题: MA 无法发现设备

症状:

排查步骤:

  1. 确认设备模式:
   curl -s http://<设备IP>/api/device/mode | jq '.mode'
   # 必须是 "sendspin"
  1. 检查网络连接:
   # 宿主机 ping 设备
   ping <设备IP>
   
   # 检查端口
   curl -s http://<设备IP>:8928/ || echo "Port 8928 not reachable"
  1. 检查 MA 日志:
   docker logs musicassistant --tail 50 | grep -i "sendspin\|error"
  1. 重启 MA 容器:
   docker restart musicassistant
问题: MA 连接后立即断开

症状:

原因: aiosendspin 版本不兼容

解决:

# 检查版本
docker exec musicassistant /app/venv/bin/pip show aiosendspin | grep Version

# 如果版本不是 6.0.5,强制降级
docker exec musicassistant /app/venv/bin/uv pip install "aiosendspin==6.0.5"
docker restart musicassistant
问题: MA 连接后无音频输出

症状:

排查步骤:

  1. 检查设备 stream_active:
   curl -s http://<设备IP>/api/sendspin/player | jq '.stream_active, .chunks_received'
  1. 检查时钟同步:
   curl -s http://<设备IP>/api/sendspin/player | jq '.time_synced'
  1. 检查 underruns:
   curl -s http://<设备IP>/api/sendspin/player | jq '.underruns'
  1. 检查 DAC 输出:

5.2 HA 连接失败

问题: HA 无法发现 DLNA 设备

症状:

排查步骤:

  1. 确认设备模式:
   curl -s http://<设备IP>/api/device/mode | jq '.mode'
   # 必须是 "dlna"
  1. 检查 DLNA 服务:
   curl -s http://<设备IP>:49152/rootDesc.xml
   # 应返回 XML
  1. 检查 HA 日志:
   docker logs homeassistant --tail 50 | grep -i "dlna\|upnp"
  1. 重新添加集成:
问题: Pause/Stop 功能不可用

症状:

原因: GENA 事件回调未配置

解决:

  1. 确认 docker-compose.yml 发布了 14000 端口
  2. 确认 DLNA 集成选项:
  1. 重新配置集成
问题: 音量状态不更新

症状:

原因: 同 Pause/Stop 问题

解决: 配置 GENA 事件回调(见上)

问题: 播放媒体时设备返回 404

症状:

原因: HA 内部 URL 配置错误

解决:

  1. 确认 HA Settings → System → Network → Internal URL
  2. 必须是 http://<宿主机LAN IP>:8123(不是 localhost 或 127.0.0.1)
  3. 重新配置后重启 HA:
   docker restart homeassistant

5.3 通用问题

问题: 容器启动失败

症状:

排查:

# 查看容器日志
docker compose logs

# 检查端口占用
netstat -an | grep -E "8123|8095|14000"

# 检查 Docker 状态
docker compose ps
问题: 设备重启后 MA 需要重新连接

症状:

原因: 设备重启会清除 legacy 方言记忆(RAM 态)

正常行为:

如需加速: 重启 MA 容器重置重连计数器


6. 技术参考

6.1 Sendspin 协议握手流程(Legacy 模式)

MA (aiosendspin 6.0.5)                    KABU 设备 (v1.9-ma-ha)
        |                                         |
        |  1. WebSocket Connect                   |
        |---------------------------------------->|
        |                                         |
        |  2. client/hello (明文 JSON)            |
        |  {                                      |
        |    "client_id": "...",                  |
        |    "name": "KABU",                      |
        |    "version": 1,                        |
        |    "supported_roles": ["player@v1"],    |
        |    "player_support": {...}              |
        |  }                                      |
        |---------------------------------------->|
        |                                         |
        |  3. server/hello (明文 JSON)            |
        |  {                                      |
        |    "server_id": "...",                  |
        |    "name": "Music Assistant",           |
        |    "version": 1,                        |
        |    "active_roles": ["player@v1"]        |
        |  }                                      |
        |<----------------------------------------|
        |                                         |
        |  4. 进入 SESSION_ACTIVE                 |
        |  开始明文 JSON 消息交换                 |
        |                                         |
        |  5. stream/start (明文)                 |
        |<----------------------------------------|
        |                                         |
        |  6. 二进制音频帧 (type=4 + 时间戳)      |
        |<----------------------------------------|
        |  (重复)                                 |

6.2 DLNA AVTransport 状态机

                    Play
    STOPPED -----------------> PLAYING
        ^                        |
        | Stop                   | Pause
        |                        v
        |                    PAUSED_PLAYBACK
        |                        |
        ^                        | Stop
        |                        v
        +--------------------- STOPPED

设备状态查询:

curl -s http://<设备IP>/api/dlna/status | jq '.transport_state'

6.3 关键 API 端点

设备端
端点方法说明
/api/device/modeGET查询当前模式
/api/device/modePOST切换模式
/api/sendspin/playerGETSendspin 播放器状态
/api/sendspin/leaderGETSendspin 领导者状态
/api/dlna/statusGETDLNA 渲染器状态
/api/system/infoGET系统信息
:49152/rootDesc.xmlGETDLNA 设备描述
HA 端
服务参数说明
media_player.play_mediaentity_id, media_content_id, media_content_type播放媒体
media_player.media_pauseentity_id暂停
media_player.media_playentity_id播放
media_player.media_stopentity_id停止
media_player.volume_setentity_id, volume_level (0.0-1.0)设置音量
MA 端

通过 Web UI 操作,无直接 API 文档。

6.4 日志查看

# MA 日志
docker logs musicassistant --tail 100

# HA 日志
docker logs homeassistant --tail 100

# 过滤 Sendspin 相关
docker logs musicassistant | grep -i sendspin

# 过滤 DLNA 相关
docker logs homeassistant | grep -i dlna

# 实时监控
docker logs -f musicassistant
docker logs -f homeassistant

6.5 性能指标

Sendspin 播放器:

curl -s http://<设备IP>/api/sendspin/player | jq '{
  connected: .server_connected,
  synced: .time_synced,
  streaming: .stream_active,
  chunks: .chunks_received,
  dropped: .chunks_dropped_late,
  underruns: .underruns
}'

健康标准:

6.6 已知限制

  1. 容器内 mDNS 不可用
  1. aiosendspin 版本锁定 6.0.5
  1. 海外流媒体超时
  1. 设备重启清除 legacy 记忆
  1. HA DLNA media_duration 恒为 0

附录 A: 快速参考卡

MA 连接检查清单

HA 连接检查清单

常用命令速查

# 启动服务
cd E:\ha-ma-env && docker compose up -d

# 查看状态
docker compose ps
curl -s http://192.168.1.67/api/device/mode | jq

# 切换模式
curl -X POST http://192.168.1.67/api/device/mode -H "Content-Type: application/json" -d '{"mode":"sendspin"}'
curl -X POST http://192.168.1.67/api/device/mode -H "Content-Type: application/json" -d '{"mode":"dlna"}'

# 查看播放器状态
curl -s http://192.168.1.67/api/sendspin/player | jq
curl -s http://192.168.1.67/api/dlna/status | jq

# 查看日志
docker logs -f musicassistant
docker logs -f homeassistant

文档结束

如有问题,请参考:

使用指南固件下载返回首页