Files
soundtower-controller/README.md
T
lda Verified 038e152bbc
Checks / tests (ubuntu-latest, 3.11) (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.14) (push) Canceled after 0s
Checks / tests (windows-latest, 3.11) (push) Canceled after 0s
Checks / tests (windows-latest, 3.14) (push) Canceled after 0s
Checks / package (push) Canceled after 0s
Add MX-T40 BLE desktop controller and protocol documentation
2026-10-25 04:43:47 +07:00

4.6 KiB

Sound Tower Controller

A small, unofficial desktop remote for Samsung Sound Tower speakers. Control EQ, bass, lighting, RGB color, volume, mute, playback, and source selection through Bluetooth Low Energy.

Verified interactively on one Samsung MX-T40 with Windows. Other models and operating systems have not been verified. No firmware flashing, Samsung account, or bundled vendor software is required.

Run with uv

Use Windows Python for a Windows Bluetooth adapter. From WSL, invoke uv.exe so Bluetooth runs on Windows rather than inside WSL.

uv run soundtower --address YOUR_SPEAKER_MAC

For WSL:

uv.exe run soundtower --address YOUR_SPEAKER_MAC

Replace YOUR_SPEAKER_MAC with the Bluetooth address of your speaker. Keep it powered on, close the phone app, and click Connect. The address can also be entered in the window. uv run python -m controller remains supported, as does the earlier --with-requirements requirements.txt launch command.

Python 3.11 or newer is required; physical device testing used Windows Python 3.14. The interpreter needs Tcl/Tk. If the interpreter provided by uv lacks Tk, use a Windows Python installation with Tk support, for example:

uv run --python C:\Path\To\Python\python.exe soundtower --address YOUR_SPEAKER_MAC

Controls

  • EQ: Party, Standard, Hip-hop, EDM, Rock, Latin, House, Reggae.
  • Bass boost, volume up/down, mute, play/pause, and audio source.
  • Lighting: Off, Ambient, Party, Dance, Thunder, Star, Lover, Color.
  • RGB color picker; lighting mode is queried after a color change.
  • Readable activity log with optional raw packet display.

A command acknowledgment means the packet was received. A later status report confirms the reported setting; the log distinguishes the two. Choosing an RGB color switches the tested speaker to COLOR mode. A play/pause event does not reveal the absolute playback state.

The source menu includes protocol options that may not exist on every model. The tested MX-T40 reports Bluetooth, USB 1, AUX 1, and AUX 2.

Audio versus control

This app opens the BLE remote-control connection. Windows establishes the separate audio playback connection. Neither a BLE connection nor Windows' word “Connected” guarantees an audio output is available.

If the speaker disappears from Windows' output list, disconnect/reconnect it through Windows and select it as the sound output. Both connection orders have worked in testing; no fixed startup order is established. Once playback works, the BLE controller can operate alongside it.

The older RFCOMM/COM path is experimental and was unreliable on this MX-T40: --transport rfcomm selects it. BLE is the default.

Development

uv run --group dev python -m unittest discover -s tests -v
uv run --group dev ruff check controller tests scripts
uv run --group dev ruff format --check controller tests scripts
uv build

The first online uv run resolves dependencies and creates uv.lock; commit that lockfile after resolving it for the project. A lockfile is not yet bundled because dependency resolution was unavailable in the offline development shell.

The tests use captured packet fixtures and fake transports; they do not need a speaker, Tk, or a display. They do not replace physical compatibility tests. The optional GitHub Actions workflow runs headless tests on Windows/Linux and Python 3.11/3.14. The same commands can be used in Gitea CI.

See architecture, protocol, feature research, and contributing.

Diagnostics

List the MX-T40's advertised BLE/GATT endpoints without sending controls:

uv run python -m controller.ble_probe

Experimental Windows RFCOMM discovery:

uv run --extra diagnostics python -m controller.probe --channel 1

Preparing a repository

This development folder also contains private research inputs. Export only the controller, tests, and original documentation into a new, empty directory:

python scripts/export_project.py dist/soundtower-controller

The export uses an explicit allowlist. Firmware, APKs, extracted vendor files, decompiled Java, environment files, and caches are excluded. Initialize Git in that exported directory before adding a GitHub or Gitea remote. No remote is configured and nothing is uploaded automatically.

Project status

This is an independent interoperability project, not an official Samsung or Qualcomm product. It contains original controller code and protocol notes, not redistributed firmware or application code. A project license has not yet been selected; no open-source license grant is currently declared.