Skip to content
wsPublic

About

Programmatically interact with Anker SoundCore Work (D3200) devices without ever connecting to Anker's cloud - Not associated with Anker

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Soundcore Work D3200

Talk to the Anker Soundcore Work (D3200) voice recorder pendant thing without the Anker app or cloud: read its status, set its clock, and list, download, and decrypt recordings on your own machine. The core protocol is implemented in Rust and available from Python and JavaScript. Not affiliated with Anker. Licensed under 0BSD: use it for any purpose, without warranty or liability.

crates/
  soundcore-d3200-protocol/   protocol, crypto, client flows, test vectors
  bestechnic-ota/             BES firmware image inspection
python/
  soundcore-d3200/            client: Bluetooth LE, Classic Bluetooth, Wi-Fi
  soundcore-d3200-core/       PyO3 bindings and models
  bestechnic-ota/             PyO3 bindings for BES inspection
js/
  client.ts                   D3200Client (Web Bluetooth)
  src/                        wasm-bindgen bindings

Rust has no I/O: each client does its own Bluetooth, Wi-Fi, timers, and file access. Firmware can be inspected but not flashed.

Python

uv add soundcore-d3200            # or "soundcore-d3200[wifi]" for Wi-Fi transfers
import asyncio
from soundcore_d3200 import SoundcoreClient

async def main():
    client = await SoundcoreClient.discover()
    async with client:
        info = await client.get_device_info()
        print(info.firmware_version, f"{info.battery.recorder_percent}%")
        await client.sync_time()  # set the recorder's clock to local time

        session, _, _ = await client.establish_encryption()
        for recording in await client.list_all_files():
            await client.download_file_to(
                recording.file_id, session, f"{recording.file_id}.ogg",
                recorded_at=recording.recorded_at,  # written to the Ogg DATE tag
            )

asyncio.run(main())

See the Python packages overview and client guide.

JavaScript

Build the wasm package and D3200Client into js/pkg/:

mise run build:js

Then, in a page served from localhost or HTTPS in a browser with Web Bluetooth:

<button id="connect">Connect</button>
<script type="module">
import { D3200Client } from './js/pkg/client.js';

document.querySelector('#connect').addEventListener('click', async () => {
  const client = await D3200Client.request(); // device picker; needs a click
  try {
    const info = await client.deviceInfo();
    console.log(info.firmware_version, `${info.battery.recorder_percent}%`);
    await client.syncTime();

    await client.establishSession();
    const files = await client.listFiles(); // [{ file_id, duration_ms, recorded_at, ... }]
    if (files.length) {
      const ogg = await client.downloadOgg(files.at(-1).file_id);
      window.open(URL.createObjectURL(ogg));
    }
  } finally {
    client.disconnect();
  }
});
</script>

js/demo/index.html is a complete page: run python3 -m http.server from the repository root and open http://localhost:8000/js/demo/. See the JavaScript guide.

Features

Task Python (SoundcoreClient) JavaScript (D3200Client)
Device info: firmware, serial, storage get_device_info() deviceInfo()
Battery and charging get_battery(), BatteryEvent battery()
Set the clock sync_time() syncTime()
List recordings, with start times list_all_files() listFiles()
Download as Ogg/Opus download_file_to(), download_file_bytes() downloadOgg(), downloadRecording()
Stream decrypted Opus packets stream_file() downloadFile()
Delete recordings delete_files() —
Follow a live recording stream_realtime() —
Wi-Fi transfer open_wifi_hotspot(), create_wifi_transfer() — (browsers can't join the hotspot)
Pairing and authentication bind_and_store(), authenticate_from_store() —
Device logs download_device_logs_to() —

Development

mise manages the Rust toolchain at the root; Python and JavaScript tools are declared in their respective directories:

mise install             # Rust
mise -C python install   # uv, when working on Python
mise -C js install       # Node and wasm-bindgen, when working on JS
mise run ci              # everything CI runs
mise tasks               # lint, test, test:rust, test:python, test:js, build:js, check:boundaries

About

Programmatically interact with Anker SoundCore Work (D3200) devices without ever connecting to Anker's cloud - Not associated with Anker

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages