Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Panel-wear tracking

What this gives you. Brightness-weighted on-hours per display, visible in the web dashboard and via GET /api/wear, with an advisory after no long standby window has occurred in 96 h.

When to use it. When you want to know whether your panel is getting the long dim it needs. Tracking is on by default; turn it off with wear.enabled = false if on-hours accounting is not useful for your setup.

Quick setup. Tracking is on by default — the dashboard panel-exposure card and dormantctl status are the readout:

dormantctl status

dormant records brightness-weighted panel on-time and shows it in the web dashboard. v1 measures and advises; it does not alter blank/wake timing.

What it records

For displays with readable brightness (ddcci and samsung-tizen), the tracker samples panel state every wear.sample_interval (default 60s) and records:

  • total_on_hours — brightness-weighted on-time. One hour at 50% brightness adds 0.5 hours. Blanked, blanking, and waking time adds zero.
  • seeded_usage_hours — a DDC/CI panel's lifetime VCP 0xC0 counter, read once when a new ledger is created and available.
  • last_long_dwell_epoch_s — the last blanked dwell lasting at least wear.short_cycle_dwell (default 10m).

render_screensaver attributes each loaded source frame from its luma grid and local wear heat when wear-even metadata is available. The black overlay attributes zero. Missing luma, heat, or journal data fails open to uniform attribution and logs wear_screensaver_luma_fallback; scan and journal failures also emit screensaver_luma_scan_failed and screensaver_item_journal_overflow. Playback and blanking continue.

The ledger has a wear.grid_rows × wear.grid_cols grid for future spatial attribution. v1 writes the same value to every cell. It does not know which region or content was shown.

displays.<id>.panel_type accepts "woled", "qd-oled", or "unknown" and is stored in the ledger. v1 does not change its wear formula by panel type and does not auto-detect the value.

Advisory

The panel-exposure card reports how long the display has gone without a blanked dwell of at least wear.short_cycle_dwell. After wear.advisory_after (default 96h), it shows an advisory such as:

no long standby window in 5 days

The day count is also returned by GET /api/wear. The advisory never forces a rest window, blank, or state-machine transition.

Ledger files

Each display gets one JSON ledger under:

$XDG_STATE_HOME/dormant/wear/          # when XDG_STATE_HOME is set
~/.local/state/dormant/wear/           # fallback

The filename uses the stable display identity where available: DDC/CI EDID manufacturer/model/serial, samsung:<host>, or the config display id. Writes are atomic and mode 0644; the ledger contains no credentials.

dormant persists every wear.persist_interval (default 5m), on shutdown, and when tracking is disabled at runtime. A crash can lose at most one persistence interval. Orphaned ledgers are not pruned automatically.

Delete the wear/ directory to erase the history. New ledgers are created on the next sample.

Configuration

Tracking is enabled by default. While wear.enabled = false, the tracker takes no samples and performs no ongoing ledger I/O.

[wear]
enabled = true
sample_interval = "60s"
persist_interval = "5m"
read_timeout = "2s"
grid_rows = 9
grid_cols = 16
fallback_brightness = 0.5
screensaver_factor = 0.35
short_cycle_dwell = "10m"
advisory_after = "96h"

[displays.monitor]
panel_type = "qd-oled"
KeyDefaultDescription
wear.enabledtrueEnable tracking and ledger I/O
wear.sample_interval"60s"Panel-state sample interval
wear.persist_interval"5m"Ledger write interval
wear.read_timeout"2s"Read budget for one panel sample
wear.grid_rows9Logical grid rows; uniform in v1
wear.grid_cols16Logical grid columns; uniform in v1
wear.fallback_brightness0.5Brightness fraction when readback fails
wear.screensaver_factor0.35Fixed factor during render_screensaver
wear.short_cycle_dwell"10m"Blanked dwell counted as a long rest window
wear.advisory_after"96h"Time without a long rest window before advising

Screensaver ordering is host-side estimation, not panel telemetry. order = "wear-even" uses luma and local heat; wear_temperature defaults to 0.05 and shift_heat_bias to 0.25. Flat luma buckets mean dark = .15, medium = .45, and bright = .75. Missing or overflowing grids fall back with a WARN. This milestone adds no schema-version bump, panel-type weighting, or RGB weighting.

The tracker is local-only. Its sole network surface is the loopback web API; there is no telemetry, analytics, cloud sync, or phone-home path.