Skip to content

Add per-device night sleep schedule (quiet hours)#25

Open
mochlast wants to merge 4 commits into
usetrmnl:mainfrom
mochlast:feat/device-sleep-schedule-clean
Open

Add per-device night sleep schedule (quiet hours)#25
mochlast wants to merge 4 commits into
usetrmnl:mainfrom
mochlast:feat/device-sleep-schedule-clean

Conversation

@mochlast

@mochlast mochlast commented Jun 12, 2026

Copy link
Copy Markdown

Adds an optional per-device quiet-hours / night sleep schedule, like other self-hosted TRMNL servers: during the configured window the device deep-sleeps for the whole night in a single cycle instead of polling, saving battery and avoiding nighttime e-ink refreshes.

Screenshots

On the device Per-device settings
TRMNL device showing the sleep screen Night Sleep settings in the device edit form

How it works

During the device poll (GET /api/display), if the device is inside its sleep window the response returns refresh_rate = seconds-until-wake, so the firmware sleeps until the wake time and polls once. The window is evaluated in the existing DEFAULT_TIMEZONE (same timezone used by the clock/date widgets) and supports ranges that cross midnight (e.g. 22:0007:00).

Two per-device modes (showSleepScreen):

  • false (default) — keep the current screen frozen on display until morning.
  • true — show a dedicated sleep screen (crescent moon + "Sleeping until HH:MM"), generated as a 1-bit e-ink PNG via Sharp (new SleepScreenService, mirroring DefaultScreenService).

The admin "Current Screen" preview reflects the sleep screen during quiet hours too, so it matches what the device shows.

Changes

  • display.service.ts: getQuietHoursSeconds() helper + wiring in getDisplayContent() (sleep-screen short-circuit / freeze-mode refresh override) and getCurrentScreenImage() (preview).
  • sleep-screen.service.ts (new): generates/caches the sleep screen per resolution + wake time, served from /assets.
  • Device.showSleepScreen added to the Prisma schema. The sleepStartAt/sleepStopAt columns already existed; everything is applied via prisma db push (no migration file needed).
  • Device update DTO/service pass the fields through; the device edit form gets a "Night Sleep" section (enable toggle, start/end time inputs, sleep-screen toggle).
  • Unit tests for the quiet-hours logic (in/out of window, midnight wrap, both display modes, preview).

Testing

402 backend unit tests pass. Verified end-to-end on a real TRMNL device (firmware 1.7.8): inside the window the device fetches the sleep screen and sleeps until the configured wake time; outside the window it behaves normally.

image

🤖 Generated with Claude Code

mochlast and others added 2 commits June 12, 2026 13:48
Devices can now be configured with a nightly quiet-hours window. During
the window the display endpoint returns refresh_rate = seconds-until-wake,
so the device deep-sleeps the whole night in one cycle (battery saving, no
nighttime e-ink refreshes) and wakes at the configured time.

Two per-device modes (showSleepScreen):
- false (default): keep the current screen frozen until morning
- true: show a dedicated sleep screen (crescent moon + "Sleeping until HH:MM"),
  generated as a 1-bit e-ink PNG via Sharp (new SleepScreenService)

The window is evaluated in the global DEFAULT_TIMEZONE and supports ranges
that cross midnight. The sleepStartAt/sleepStopAt columns already existed in
the schema; adds showSleepScreen (applied via prisma db push, no migration).
Wires the fields through the device update DTO/service and the device edit
form (toggle + time inputs). Unit tests cover the quiet-hours logic.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The preview path (getCurrentScreenImage) rendered the playlist screen
regardless of quiet hours, so the admin UI showed the normal screen even
while the device was displaying the sleep screen. Render the sleep screen
in the preview too when the device is within its sleep window and
showSleepScreen is enabled (freeze mode already shows the current screen).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@mochlast mochlast force-pushed the feat/device-sleep-schedule-clean branch from 25bba7a to 73e776e Compare June 12, 2026 11:48
mochlast and others added 2 commits June 12, 2026 13:51
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
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