Skip to main content

PicPak BLE protocol spec, client and CLI tool

Project description

PicPak BLE client

An independent Python client for the PicPak e-ink photo frame.

Disclaimer

This is an independent, unofficial project. It is not affiliated with, authorized by, or endorsed by the makers of PicPak. "PicPak" is used only to identify the hardware this client talks to. It is intended for use with a device you own, to interoperate with hardware you have bought. Use it at your own risk.

Install

Python 3.11 or later is required.

The core library is dependency-free — it implements the raw protocol. Optional extras pull in what each layer needs:

  • [cli] — the picpak command-line tool (Click, Pillow, bleak, tqdm)
  • [client] — the BLE client only (bleak)
  • [image] — the image encoder only (Pillow)

The picpak command needs the cli extra, so install with it:

pip install "picpak-ble[cli]"

For local development, sync every extra instead:

uv sync --all-extras

On Linux, BLE access may also require the usual BlueZ permissions. Keep the official app disconnected while using this tool.

Use

Find the device:

uv run picpak scan

On macOS the identifier is normally a UUID rather than a hardware MAC address. Inspect the slot table before writing:

uv run picpak slots --device DEVICE_ID

To avoid repeating the identifier, you can set the PICPAK_DEVICE environment variable. Every command that connects to the screen uses it as the default for --device; an explicit option still takes precedence.

export PICPAK_DEVICE=DEVICE_ID
uv run picpak slots
uv run picpak name

Upload as many files as desired to the first available slots:

uv run picpak upload --device DEVICE_ID photo1.jpg photo2.png photos/*.jpg

To replace consecutive slots explicitly:

uv run picpak upload --device DEVICE_ID --start-slot 20 --overwrite photos/*.jpg

Add --display-last to show the final uploaded photo. Other useful commands:

uv run picpak info --device DEVICE_ID
uv run picpak name --device DEVICE_ID
uv run picpak name --device DEVICE_ID "Kitchen PicPak"
uv run picpak config --device DEVICE_ID
uv run picpak config --device DEVICE_ID --refresh-interval 3600 --open-door-refresh
uv run picpak bindings --device DEVICE_ID
uv run picpak status --device DEVICE_ID
uv run picpak download --device DEVICE_ID 20 photo.picpak.bin
uv run picpak display --device DEVICE_ID 20
uv run picpak erase --device DEVICE_ID 20 21 22
uv run picpak encode photo.jpg photo.picpak.bin

encode works without a device and is useful for inspecting the exact 30,000-byte photo representation.

Cropping

Both upload and encode take --crop MODE for sources that are not 4:3.

The default, smart, slides the crop window to where the image's saliency is (measured as color contrast against the scene's mean), and letterboxes onto a white matte instead when no crop could hold most of the salient content. center always takes the middle crop, and letterbox always fits the whole image.

Dithering

Both upload and encode also take --dither MODE.

The default, app, matches the official app's dithering. There are no tunables here.

--dither perceptual is an alternative tuned for image quality: serpentine Floyd-Steinberg diffusion in linear light with chroma-weighted Oklab color matching, clamped to the panel gamut.

  • --tone N adjusts its midtone lift: 1.0 reproduces the source's reflectance exactly (which looks murky on the dim reflective panel), lower values are brighter, and the default 0.45 matches the brightness the app scheme produces.
  • --retention N sets the fraction of dither error that is diffused; values below 1.0 let near-solid areas collapse to solid ink for extra contrast at some cost in tonal accuracy, and the default 0.65 was picked by comparing values on the physical panel. The perceptual mode also compensates for the panel's actual ink colors using measured values.

Notes

  • If the BLE backend reports an implausibly small MTU, the upload command stops before writing. --chunk-size N can override its calculation when the backend has in fact negotiated a larger MTU but does not report it correctly. Use at least 118 bytes and no more than ATT_MTU - 12.
  • See PROTOCOL.md for the packet layouts, characteristic routing, image palette, and dithering algorithm.
  • The current shipping firmware appears to leave the BLE photo-read request unimplemented, so download is expected to time out even though the client-side receiver is complete.

License

Released under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

picpak_ble-0.1.0-py3-none-any.whl (26.3 kB view details)

Uploaded Python 3

File details

Details for the file picpak_ble-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: picpak_ble-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for picpak_ble-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2929e631027852d0ddb905f4a059158a5a22fea6b6e2ffe8af7f45a8f6b4d825
MD5 74fdfba230729bc2305cafa30f05e9f3
BLAKE2b-256 0ca4f63deb1abda73be1dd18e83bfc0b9d87059e6ab136bfaf4d4c765927dde5

See more details on using hashes here.

Provenance

The following attestation bundles were made for picpak_ble-0.1.0-py3-none-any.whl:

Publisher: ci.yml on akx/picpak-ble

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page