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]— thepicpakcommand-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 Nadjusts its midtone lift:1.0reproduces 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 Nsets 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 Ncan 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 thanATT_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
downloadis expected to time out even though the client-side receiver is complete.
License
Released under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2929e631027852d0ddb905f4a059158a5a22fea6b6e2ffe8af7f45a8f6b4d825
|
|
| MD5 |
74fdfba230729bc2305cafa30f05e9f3
|
|
| BLAKE2b-256 |
0ca4f63deb1abda73be1dd18e83bfc0b9d87059e6ab136bfaf4d4c765927dde5
|
Provenance
The following attestation bundles were made for picpak_ble-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on akx/picpak-ble
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
picpak_ble-0.1.0-py3-none-any.whl -
Subject digest:
2929e631027852d0ddb905f4a059158a5a22fea6b6e2ffe8af7f45a8f6b4d825 - Sigstore transparency entry: 2185220963
- Sigstore integration time:
-
Permalink:
akx/picpak-ble@c70ce73c33046fb8e00ce5996b4298df3862e27b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/akx
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@c70ce73c33046fb8e00ce5996b4298df3862e27b -
Trigger Event:
push
-
Statement type: