Skip to content

feat: add a refine dithering option to image uploads - #141

Merged
g4bri3lDev merged 3 commits into
mainfrom
feat/dbs-refinement
Oct 9, 2026
Merged

g4bri3lDev merged 3 commits into
mainfrom
feat/dbs-refinement

Conversation

@g4bri3lDev

Copy link
Copy Markdown
Member

Summary

Two commits:

fix: update py-opendisplay to 7.18.1

7.16.0 → 7.18.1 in manifest.json, pyproject.toml and uv.lock. For users this brings:

  • Image preparation off the event loop: upload_image() used to dither on HA's loop. The integration's own prepare_image() path was already in an executor, so this mainly helps other callers, but it's the same library fix.
  • More robust BLE: the notification queue is flushed on every disconnect, and config reads ignore stray frames.
  • Config write-back keeps packets the parser doesn't recognise (new unparsed_tail field).
  • Security: epaper-dithering 6.1.1, rebuilt with pyo3 0.29.3 for two advisories.

Diagnostics now redact unparsed_tail. It holds raw bytes of unrecognised config packets, so its content is unknown; without redaction it would appear as hex in downloads. A new test uses a non-empty value and asserts REDACTED. (The main snapshot shows '', because HA's redaction leaves empty values as they are.) This was flagged by Copilot on the equivalent core change.

feat: add a refine dithering option to image uploads

New optional refine_dithering switch (off by default) on upload_image (under Additional options) and drawcustom, passed to prepare_image(..., dbs=...).

DBS (Direct Binary Search) refines the dithered image to minimise the error as perceived at a normal viewing distance. The library sizes its eye model from the panel's real pixel density, taken from the config's physical size. It typically reproduces colours and tones more faithfully (see the epaper-dithering README comparison), but it's slower: ~0.3 s for 800×480 on a multi-core desktop, longer on a Pi. It runs inside the existing executor job, so it never blocks the loop, and with the sleepy-device queue it's computed once at queue time.

UI metadata follows each action's existing pattern: upload_image is translated through strings.json and translations/en.json; drawcustom uses inline name/description in services.yaml. No icons.json change, since fields have no icons there.

Tests

  • 5 new tests:
    • refine_dithering reaches prepare_image as dbs (off by default, on when set), for both actions;
    • unparsed_tail redaction.
  • Both matrix legs: scripts/test 232 passed, scripts/test --min-ha 232 passed.
  • ruff check and ruff format --check clean; scripts/verify_translations.py passes; compileall passes.

Heads-up

#133 also bumps py-opendisplay (to 7.17.0) in the same three files, so whichever merges second needs a quick rebase. Keep 7.18.1.

Image preparation for uploads now runs in a worker thread instead of on
Home Assistant's event loop, BLE disconnects and config reads are more
robust, unrecognised device-config data is kept when the configuration
is written back, and the bundled dithering library is rebuilt with a
patched PyO3 (security advisories).

Diagnostics now redact the new raw `unparsed_tail` config bytes, whose
content is unknown.
New optional "Refine dithering" switch (off by default) on the
upload_image and drawcustom actions. It refines the dithered image for
how it is perceived at a normal viewing distance, which typically
reproduces colors and tones more faithfully, at the cost of a noticeably
slower upload. Passed to py-opendisplay as dbs=True.
@g4bri3lDev
g4bri3lDev merged commit 1c13f6e into main Oct 9, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant