Browse documentation

🧭 Start Here

Blackcap Overview ✨ Blackcap Feature Catalog Installation First Run

🚀 Deploy Blackcap

Platform Stacks and Raspberry Pi Hardware Raspberry Pi Deployment Raspberry Pi Client Services GCP Deployment Application Updates Environment Variables and Secrets Reverse Proxy and TLS Background Jobs and Schedules

🛠️ Administer Blackcap

Organizations Users, Permissions, and Authentication Configuration Workspace Backups and Restore Database Administration Regression Testing Performance and Job Status Audit, Access Activity, and Logging GeoIP and Access Location Data Retention and Purge Support Requests API Tester and Postman Instance Reporting

🍽️ Use Recipes

Recipes and the Recipe Library Recipe Import and Discovery Recipe Editing and Cache Artifacts Recipe Sharing Social Recipe Import AI Recipe Image Generation

📅 Plan Meals

Meal Planner

🛒 Use Shopping Lists

Shopping Lists and Shop a List External and Household Shopping 🧩 Chrome Extension Shop With

🧺 Manage Kitchen Inventory

🧺 Kitchen Inventory

🖥️ Use Displays

Displays and Connections Assigning and Scheduling Display Content Remote Pi Client E-Ink Rendering Menu Refresh and Rendering Noun Project Footer Images

🧑‍🍳 Cook with Let’s Cook

🧑‍🍳 Let’s Cook 🧑‍🍳 Let’s Cook Controls and Timers

🤖 Use and Administer AI

🤖 AI in Blackcap 🤖 AI Providers and Connections 🤖 AI Seeds and Usage

🧩 Use the Chrome Extension

🧩 Blackcap Chrome Extension 🧩 Chrome Extension Recipe Capture 🧩 Chrome Extension Shop With 🧩 Chrome Extension Release and Privacy

🎮 Play Games

🎮 Games and Trivia

🔌 Integrations

Email Integration Cloud Storage Integrations Voice Assistants Shop With Integrations Authentication Providers

⚙️ Develop Blackcap

Application Architecture Database Service and Data Access SQLite and PostgreSQL Database Migrations Background Job Architecture Testing API Architecture Security and Organization Scoping UI, Icons, and Documentation Assets Blackcap-Safe Emoji Documentation Standards Terminology

⚠️ Troubleshoot Blackcap

⚠️ Troubleshooting Deployment Troubleshooting Display Troubleshooting Recipe Import Troubleshooting 🤖 AI Troubleshooting Backup Troubleshooting Database Troubleshooting Diagnostic Organization Clones Support Requests

E-Ink Rendering

Audience: Developer, Deployment Administrator, Support Related: Overview · Remote Pi Client · Menu Rendering · Overview

The supported Waveshare 13.3-inch K path is 960×680 with four grayscale levels. Blackcap prepares panel-ready PNG and, where appropriate, verified gray4 controller-plane transport artifacts for local and remote clients. Local and remote paths share render profiles and validation rules.

E-ink design must account for the physical panel: thin lines should be black rather than light gray, the Let’s Cook progress border is black, the progress fill may be light gray, meal-plan separators are 1 px black, and full refresh remains the established reliable path.

Four-gray rendering and transport

Blackcap uses one Type K rendering contract for attached local e-ink displays and paired remote Raspberry Pi clients:

  • PNG, 960 × 680;
  • Pillow mode L;
  • gray values 0, 128, 192, and 255 only;
  • a paired blackcap-gray4-planes-v1 controller artifact containing the exact 0x24 and 0x26 RAM planes.

The PNG remains the Admin/UI preview. The controller artifact is the hardware input.

Content coverage

The controller artifact and bulk-write path apply to full four-gray updates for:

  • Menu;
  • Daily, weekly, today-and-tomorrow, and monthly Meal Plan views;
  • Recipe display rendering;
  • Let’s Cook;
  • saved Menu restoration;
  • deep-clean frame restoration.

Hosted receivers, kiosks, mock displays, and other non-Type-K profiles keep their existing output behavior and do not create a controller artifact.

Local and remote behavior

Remote Pi client

The server prepares both artifacts. A client-only Pi downloads only the controller artifact. A Pi that also hosts Blackcap downloads the controller artifact for hardware and the PNG for its local Admin UI.

Attached local e-ink

The local Blackcap server prepares the same controller artifact next to current_view.png and passes it to the hardware helper. This avoids reopening the PNG and packing the planes in the helper. If the transport is unavailable, the helper retains a panel-ready PNG fallback.

Atomic publication

The PNG and controller artifact are finalized before displays.last_preview_updated_at is advanced. That database field is now a microsecond UTC generation token and is authoritative for remote clients.

The state endpoint suppresses files whose modification time is newer than the committed generation token. This prevents both existing and newly restarted clients from seeing an intermediate PNG before its matching controller transport is ready.

Pixel mapping

The mapping matches Waveshare's official getbuffer_4Gray() and display_4Gray() implementation:

PNG gray Meaning RAM 0x24 RAM 0x26
255 White 0 0
192 Light gray 1 0
128 Dark gray 0 1
0 Black 1 1

Pixels are packed left-to-right, MSB first. Regression coverage packs and reconstructs an entire 960 × 680 frame, including text, a strikethrough rule, gray blocks, the final row, and byte boundaries, then requires exact pixel equality.

Hardware path

All optimized full four-gray paths use the shared eink_hardware_push_service:

  1. initialize the Type K four-gray controller;
  2. bulk-write the 81,600-byte 0x24 plane;
  3. bulk-write the 81,600-byte 0x26 plane;
  4. invoke the standard 0x22 / 0xC7 / 0x20 four-gray update sequence;
  5. wait for BUSY to clear;
  6. sleep and release the panel.

This replaces Waveshare's per-byte Python loops while preserving the controller mapping and waveform.

Let’s Cook strikethrough

For Type K output, completed-item strikethrough rules are rendered in solid black instead of medium gray. The line is positioned from the visible glyph bounding box and scaled with the font. This avoids a visually segmented strike where a gray rule crosses black glyphs, while hosted/color output retains its existing muted-gray styling.

Immutable preview generations

Display renderers atomically replace the display-scoped current_view PNG. For a supported Type K target, Blackcap then generates and validates the matching controller transport beside that PNG. Only after both steps finish does it advance the display row's UTC generation token. Pull clients version the artifact from that committed database token, so an in-progress render does not look new until the complete PNG/transport pair is ready.

A failed or concurrent later render can overwrite the working file without affecting the previously committed bundle. If controller-transport creation fails, Blackcap publishes the validated panel-ready PNG as a compatibility fallback so the physical display is not left indefinitely on stale content.

Remote artifact diagnostics

Remote clients validate paired Type K gray4 transport and PNG artifacts whenever both are downloaded. The service log reports transport_png_match, pixel mismatch count, and content hashes. An exact match proves the server preview and controller-plane artifact contain the same four gray states; a remaining visual difference is then in the client driver/LUT/panel path rather than the network artifact.

BLACKCAP_EINK_GRAY4_PUSH_MODE controls only content that is still published as native four-gray output. The default auto mode uses the verified bulk-plane path for structured content. An explicitly selected native_four_gray Menu uses the installed Waveshare PNG path because the one-write-per-plane experiment produced streaking on photographic frames. bulk and official remain diagnostic overrides. One-bit Menu modes do not use this setting.

Type K Menu strategy

Photographic Menu content now defaults to the organization-scoped crisp_bw strategy. The server publishes an exact one-bit PNG, does not publish a gray4 transport for that generation, and the client uses the normal fast black/white panel path. perceptual_four_tone provides a patterned black/white alternative, while native_four_gray remains experimental. See eink-rendering.md. Structured Meal Plan, Recipe, and Let’s Cook gray4 updates retain the fast bulk transport without a mandatory white pre-clear.

Visual style rules

This guide defines the display-language rules Blackcap should use for the Waveshare 13.3-inch Type K four-gray e-ink panel and any future grayscale e-ink targets with similar characteristics.

Core principles

  1. Thin lines must be black. Light gray does not read reliably when used as a 1px rule or outline.
  2. Light gray is for mass, not detail. Use it for filled regions, progress fills, and larger highlighted areas.
  3. Critical status marks should be black. Examples include strikethrough rules, separators, checkbox outlines, progress bar outlines, and table rules.
  4. Dark gray is optional secondary emphasis. It can work for larger shapes, but should not replace black for small, important lines.
  5. Prefer panel-native values. Type K output should use only 0, 128, 192, and 255.

Approved grayscale roles

Role Type K value Usage
Black 0 Text, thin lines, borders, separators, strikethroughs, icon details
Dark gray 128 Secondary fills, subdued labels, larger secondary UI areas
Light gray 192 Progress fills, large highlight fills, soft chips/cards where enough area exists
White 255 Backgrounds and negative space

Thin-line rules

These should render in black on e-ink:

  • progress bar outlines
  • strikethrough lines
  • row separators
  • divider rules
  • checkbox outlines
  • table borders
  • underlines and other 1px emphasis strokes

Do not use light gray for any of the above.

Let's Cook guidance

  • Progress bar outline: black
  • Progress bar background: white
  • Progress fill: light gray
  • Completed-item strikethrough: black
  • Primary text: black
  • Secondary labels may use dark gray only when they are not thin rules

Meal Plan guidance

  • Row separators: 1px black
  • Table borders: black for e-ink
  • Text: black
  • Decorative faint separators used on color displays should promote to black on e-ink when they are thin rules

Implementation notes

  • For e-ink-targeted renderers, choose colors based on the display profile before drawing.
  • Do not rely on post-processing to rescue poor contrast decisions.
  • When adding a new component, ask: is this a thin line or a filled area?
    • thin line → black
    • filled area → consider light gray or dark gray

Current applications

These rules are currently applied to:

  • Let's Cook progress bar outline/fill
  • Let's Cook completed-item strikethroughs
  • Meal plan row separators

Future e-ink UI updates should follow this guide by default.

Monthly deep clean

inky_deep_clean.py performs the established full-panel ghosting cleanup sequence for an attached e-ink display:

white → black → white

The script then restores the prior image in a separate display session so the panel returns to useful content with a clean, high-contrast baseline. It uses the shared display lock and must not run while another local display operation owns the panel. Client mode and deployment choices may intentionally suppress local deep cleaning when a remote server owns the attached panel.

Pi deployment tooling can install the monthly deep-clean schedule for hosts that physically drive an e-ink panel. See Background Jobs and Schedules.

Hardware baseline

tools/run_waveshare_13in3k_baseline.py is an isolated hardware diagnostic. It bypasses Blackcap rendering, remote-client downloads, controller-plane transport, and tone compensation. It uses only the installed Waveshare epd13in3k driver and mirrors the official demo's four-gray sequence.

Stop the remote client first so it cannot replace the test image:

sudo systemctl stop blackcap-client.service

Run the generated official four-gray stage and then Waveshare's official scale bitmap:

cd /home/pi/Blackcap-Pi
sudo /home/pi/inky_env/bin/python3 tools/run_waveshare_13in3k_baseline.py \
  --download-official-scale-bmp

The generated stage remains visible for 15 seconds. The official 13in3k_Scale.bmp is then displayed and left on the panel while the controller is put to sleep.

Restart the Blackcap client after photographing the result:

sudo systemctl start blackcap-client.service
sudo journalctl -u blackcap-client.service -f

Offline use

Download 13in3k_Scale.bmp separately and provide it without allowing the script to modify or resize it:

sudo /home/pi/inky_env/bin/python3 tools/run_waveshare_13in3k_baseline.py \
  --scale-bmp /path/to/13in3k_Scale.bmp

Omit both scale-BMP options to leave the generated official-style demo on the panel as the final image.

Render-only validation

/home/pi/inky_env/bin/python3 tools/run_waveshare_13in3k_baseline.py --render-only

This writes /tmp/waveshare_13in3k_generated_baseline.png without touching the e-ink hardware.

Type K menu rendering

Blackcap treats photographic Menu captures differently from structured content on the Waveshare 13.3-inch Type K panel.

Organization setting

menu.type_k_render_mode controls Menu rendering only:

  • crisp_bw — default and recommended. Uses deterministic ordered black/white dithering and the normal fast one-bit panel refresh.
  • perceptual_four_tone — uses four apparent tonal bands built from repeatable black/white halftone patterns. It still uses the fast one-bit panel refresh.
  • native_four_gray — experimental. Uses Waveshare's four physical gray states, the official Menu driver path in client auto mode, and the full-white baseline sequence.

The setting is organization-scoped and is available on Menu Mode Settings. It does not affect Meal Plan, Recipe, or Let's Cook.

Remote client transport

For crisp_bw and perceptual_four_tone, the state API advertises:

  • pixel_format: bw1
  • gray_levels: [0, 255]
  • no gray4 controller-plane transport

The client downloads the exact panel-ready PNG and invokes the normal one-bit Waveshare display path. BLACKCAP_EINK_GRAY4_PUSH_MODE is ignored because the artifact is not gray4.

For native_four_gray, the state API advertises pixel_format: gray4, publishes the paired controller-plane artifact, and retains the existing gray4 diagnostics.

Performance

Structured gray4 content no longer performs a mandatory white pre-clear. The pre-clear remains opt-in for native Menu diagnostics. This restores Meal Plan, Recipe, and Let's Cook to the original fast bulk initialization path.

On this page