Skip to main content

🎙️ memotalk-sdk

MemoTalk S1 / AI-PEN voice recorders — fully unlocked for Python.

22 raw hardware commands distilled into 6 typed capability groups.
Scan, connect, record, stream live audio, download — in ~10 lines.

CI PyPI Python License: MIT Tests

English · 简体中文


✨ Highlights

  • 🔌 Zero-dependency protocol layer. bleak is only needed when talking to real hardware.
  • 📦 Every reply is a dataclass. No more hand-rolling pkt[3:-2] slices — batteries, file lists and settings arrive typed and validated.
  • 🎮 Built-in device simulator. Develop and test the full stack with no pen in hand.
  • 🧪 154 unit tests, byte-level asserts from real captures. The parser suite is literally a replay of genuine device traffic.
  • 📡 Live audio & level streaming. Real-time dB meter or 72 ms MP3 chunks while recording — ready for streaming ASR.
  • 🚀 Wi-Fi fast transfer. One context manager opens the hotspot, reads FTP credentials and hands you a live FTP session.

📥 Installation

pip install memotalk-sdk

Development install:

pip install -e ".[dev]"

Dependency: bleak >= 0.21 — only when connecting to a real device.


🚀 Quick Start

import asyncio
from memotalk import MemoTalkClient

async def main():
    async with MemoTalkClient() as dev:          # scan + connect + time sync + keepalive
        print(await dev.battery())               # BatteryInfo(level=5, percent=50)

        for entry in await dev.files.list():
            print(entry.name, entry.size, entry.duration_sec)

        path = await dev.files.download((await dev.files.latest()).name, "./downloads")
        print("saved", path)

asyncio.run(main())

🎚️ Record + live level meter

async with MemoTalkClient() as dev:
    await dev.record.set_realtime(False)         # 0xA4=0 -> pushes 0xA8 levels
    await dev.record.start()

    async for level in dev.stream.level():
        print(f"{level.db:6.1f} dB  {'#' * int(level.normalized * 30)}")

    await dev.record.stop()

🗣️ Record + live transcription

async with MemoTalkClient() as dev:
    await dev.record.set_realtime(True)          # 0xA4=1 -> pushes 0x90 MP3
    await dev.record.start()

    async for chunk in dev.stream.audio():       # 288 bytes = 2 MP3 frames = 72 ms
        feed_asr(chunk)                          # straight into streaming ASR

    await dev.record.stop()
    await dev.record.set_realtime(False)

📶 Wi-Fi fast transfer

async with MemoTalkClient() as dev:
    async with dev.wifi.session() as net:        # 0x87 on -> read creds -> 0x87 off
        print(net.ssid, net.password)
        print(net.ftp_config.address)

        net.join_hotspot()                       # auto-join on macOS
        ftp = net.open_ftp()                     # PASV login
        for name in net.list_audio_files(ftp):
            net.download(ftp, name, "./downloads")
        ftp.quit()

The hotspot is always closed on exit — even on exceptions.

⚙️ Settings

async with MemoTalkClient() as dev:
    print(await dev.settings.read_all())         # DeviceSettings(...)
    await dev.settings.sleep_timeout(600)        # 15~7200, or 0 = default
    await dev.settings.max_record_minutes(120)   # 1~480
    await dev.settings.usb_mass_storage(True)

🔧 Escape hatch

frame = build_frame(0x77)                        # any protocol code
reply = await dev.raw.request(frame, code=0x77, timeout=2.0)

🗺️ API Map

Group Methods
Status battery() firmware() identity() free_space() has_import_file() info() sync_time()
Record record.start() pause() resume() stop() state() set_realtime()
Stream stream.level() stream.audio() stream.states() stream.packets()
Files files.list() latest() download() download_all() delete() clear_all() sync_control()
Settings settings.read() read_all() write() sleep_timeout() max_record_minutes() usb_mass_storage()
Network wifi.enable() disable() credentials() ftp() session()
Raw raw.send() request() expect()

Full hardware ↔ SDK mapping: CAPABILITY-MATRIX.md


💻 CLI

memotalk scan
memotalk status --files
memotalk list
memotalk download --all --out ./downloads
memotalk record --seconds 5            # live level meter
memotalk record --seconds 5 --realtime # count received MP3 bytes
memotalk wifi --ls --download FILE.mp3
memotalk config --sleep 600 --usb 1
memotalk raw --hex 5A0301C080 --expect 01

# no hardware? use the simulator
memotalk --simulate status

🧱 Architecture

memotalk/
├── codec.py         CRC16 / 0x5A framing / length inference / BCD / XOR-FF
├── commands.py      22 pure command builders + channel routing table
├── parsers.py       every reply -> typed model (incl. 0x00 error frames)
├── assemblers.py    frame reassembler / 0x13 listing / 0x84 audio stream
├── transport.py     connect / write / request-reply correlation / keepalive
├── client.py        the 6 capability groups
├── discovery.py     scanning + macOS already-connected recovery
├── fake.py          device simulator
└── cli.py           command line

Length inference. The device uses three frame shapes (standard 2+len, 0x90's 3-byte length → 295, 0x84's fixed 328). codec.expected_frame_length() derives the expected byte count from any prefix, so FrameReassembler stitches frames automatically — even on low-MTU platforms.

Request-reply correlation. Predicate subscriptions are registered before writing, so fast replies are never missed. 0x00 error frames are matched too and surface as typed exceptions.

Loss-resilient transfer. On 0x84 timeouts, missing_sequences() pinpoints the first missing packet and the transfer resumes from it — automatically, with bounded retries.


🧪 Testing

# uv (recommended; pytest lives in the dev extra)
uv run --extra dev pytest -q

# or stdlib
python -m unittest discover -s tests -v
File Covers
test_codec.py CRC, framing, BCD, byte-level asserts for all 22 commands, range validation
test_commands.py builders ↔ sendable codes 1:1, write-channel routing, version consistency
test_parsers.py 24 real device captures → typed models
test_assemblers.py split / out-of-order / lost packets / CRC errors / padding truncation
test_client.py simulator-driven end-to-end flows

Every hex literal in test_parsers.py comes from real device captures.


📚 Documentation

Doc Contents
CAPABILITY-MATRIX.md Hardware atomic capability ↔ SDK capability, line by line
CHANGELOG.md Release history
docs/CODE-STRUCTURE.md Layered structure & porting notes
docs/ERRATA.md Protocol doc quirks & real-hardware findings
docs/HARDWARE-REGRESSION.md Hardware regression details & raw JSON
docs/RELEASING.md PyPI release process

🛠️ Migrating from memotalk-ble-skill

The original SKILL stays put as a protocol dictionary + reference scripts; this package is the installable client built on top of it. cmd_* names were dropped — cmd_read_battery() is now read_battery(), so migrations are just a prefix away.


⭐ Show your support

If memotalk-sdk saves you an afternoon of BLE reverse-engineering, give it a star — it helps others find it.


📄 License

MIT — Floatboat & MemoTalk. See LICENSE.

Metadata

Release files for memotalk-sdk 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for memotalk-sdk 0.1.0
File Size Uploaded Provenance Actions
memotalk_sdk-0.1.0.tar.gz 58.4 kB With provenance Details for memotalk_sdk-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for memotalk-sdk 0.1.0
File Interpreter ABI Platform Actions
memotalk_sdk-0.1.0-py3-none-any.whl Python 3 none any Details for memotalk_sdk-0.1.0-py3-none-any.whl

Total release size: 107.3 kB

Release files / memotalk_sdk-0.1.0.tar.gz

Download URL memotalk_sdk-0.1.0.tar.gz
Size 58.4 kB
Tags Source
SHA-256 checksum
How to use checksums
573219a168067ba4512e82c4cb4b17c52a1e53905d1ec0cdac16d2614d29aa08
BLAKE2b-256 checksum
How to use checksums
0d541d28a905f582f4643f4a088967ef59f1c70c7fec3917b6bbfb3b20c7d91c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / memotalk_sdk-0.1.0-py3-none-any.whl

Download URL memotalk_sdk-0.1.0-py3-none-any.whl
Size 49.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c7b630cbae42f8acfabac62f26a291305a04f7f76184a4ed4cc44c0e034b5953
BLAKE2b-256 checksum
How to use checksums
f70e9e554cb8492e4b29b80daa3180ad7863b9a739c9c31206109eca6a754334
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for memotalk-sdk 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for memotalk_sdk-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page