Dear @htilburgs,
it seems, we are in the same time-zone :-) wouldn’t be surpised even same mother-tongue …
Nevertheless, thank you for your patience and the detailed logs — they were extremely helpful in tracking this down.
What we found
The module works perfectly on my system (Pi 5, Debian Trixie, Wayland/labwc, MagicMirror 2.34.0), so we did an intensive
deep-dive comparing your setup, your MMM-Pir configuration, and your MMM-PresenceScreenControl configuration to understand why
the screen comes back after ~6 seconds on your system.
The key clue came from your own working MMM-Pir config:
mode: 3
waylandDisplayName: "wayland-0"
MMM-Pir mode 3 uses wlr-randr — the same tool you configured for MMM-PresenceScreenControl. But there’s a critical difference:
MMM-Pir internally sets WAYLAND_DISPLAY=wayland-0 (from your waylandDisplayName parameter) before calling wlr-randr.
Your MMM-PresenceScreenControl config, on the other hand, uses:
onCommand: "DISPLAY=:0 wlr-randr --output HDMI-A-1 --on --mode 1920x1080 --transform 270",
offCommand: "DISPLAY=:0 wlr-randr --output HDMI-A-1 --off",
wlr-randr is a Wayland tool — it communicates with the Wayland compositor via the WAYLAND_DISPLAY environment variable.
DISPLAY=:0 is an X11 variable and is meaningless to wlr-randr. Without the correct WAYLAND_DISPLAY, wlr-randr falls back to
guessing the socket, which results in the unstable behavior you’re seeing: the screen turns off but comes back after ~6
seconds.
This also explains why your system info shows WAYLAND_DISPLAY: undefined — MagicMirror/Electron doesn’t have it set, so any
screen command executed from the module needs to provide it explicitly.
The fix
Replace DISPLAY=:0 with WAYLAND_DISPLAY=wayland-0 in your config. You have two options:
Option A: wlr-randr (matching your working MMM-Pir setup)
onCommand: "WAYLAND_DISPLAY=wayland-0 wlr-randr --output HDMI-A-1 --on --mode 1920x1080 --transform 270",
offCommand: "WAYLAND_DISPLAY=wayland-0 wlr-randr --output HDMI-A-1 --off",
This is the minimal change — same tool, same parameters, just the correct environment variable.
Option B: wlopm (recommended, more robust)
wlopm is purpose-built for display power management on Wayland. Unlike wlr-randr --off (which removes the output from the
compositor layout), wlopm --off uses the Wayland power management protocol (DPMS-level) — it turns the display hardware off
without affecting window layout. This is what I use on my system.
First install it (it’s in the Trixie repos):
sudo apt install wlopm
Then configure:
onCommand: "wlopm --on HDMI-A-1",
offCommand: "wlopm --off HDMI-A-1",
Note: wlopm doesn’t need WAYLAND_DISPLAY explicitly — the default fallback to wayland-0 works reliably on Trixie. And since
wlopm controls hardware power state, it doesn’t need --mode or --transform on the on command — the display simply wakes up with
its previous settings intact.
For reference, the https://github.com/Jopyth/MMM-Remote-Control/blob/master/docs/guide/monitor-control.md documents wlr-randr
as the recommended Wayland screen control option, including the hint to set WAYLAND_DISPLAY if needed.
About the startup behavior (screen stays on)
You mentioned the screen stays on after MagicMirror starts until you trigger the PIR. The startup fix from commit 39d28d6 does
work — it turns the screen off ~1 second after startup. But since your offCommand wasn’t working correctly (the DISPLAY=:0
issue), the screen appeared to “stay on.” Once you fix the command, the screen should turn off shortly after startup if nobody
is in front of the PIR.
You also asked: “Why not the time from counterTimeout?” — That’s a fair point. On my system, counterTimeout is 600 (10
minutes), so turning off after 1 second is the desired behavior — I want to see that the restart worked, but not wait 10
minutes. For your setup with counterTimeout: 30, having 30 seconds of screen-on after startup would make more sense.
I’m planning a new config parameter startupGracePeriod that lets you define how long the screen stays on after module start
before the presence logic kicks in. This way each user can choose independently of their counterTimeout. I’ll include this in a
future release.
Upcoming improvement: cronMonitor efficiency
While investigating your issue, I discovered that the internal cron monitor (which checks for always-on/ignore time windows)
sends updates to the frontend every second, even when nothing has changed and the screen is off. This causes unnecessary DOM
rebuilds and is inefficient, though it’s not the cause of your screen-comes-back problem. I’ll fix this in the next release to
make the module quieter after screen-off.
About the debug logging
Now that we’ve identified the root cause, you can set debug: “off” in your config again. The debug output you saw (gpiomon
lines in pm2 logs) comes from the PIR library and goes to the console. The module’s own debug logging (updatePresence,
startCounter, updateScreen, etc.) intentionally writes to a separate log file (MMM-PresenceScreenControl_local.log in the
module directory) rather than to pm2 logs. This keeps the debug output focused and separated from the noise of all other
modules — much easier to analyze when troubleshooting a specific issue. If you ever need to debug the module again, check that
file instead of pm2 logs.
Summary
- Screen comes back after 6 seconds: Replace DISPLAY=:0 with WAYLAND_DISPLAY=wayland-0 (Option A), or switch to wlopm (Option
B)
- Screen stays on after startup: Should be fixed once Option A or B is applied. A startupGracePeriod parameter is planned for
a future release.
- Log prefix [MMM-Pir]: Already fixed in your version ✓
Please let me know if Option A or B resolves the screen-comes-back issue!
Warm regards,
Ralf