Skip to content

Commit 3045a5f

Browse files
feat: update monitor control commands to use Wayland and enhance documentation
1 parent 0d3eb81 commit 3045a5f

File tree

3 files changed

+178
-3
lines changed

3 files changed

+178
-3
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](https://semver.org/).
77

8+
## [unreleased](https://github.com/jopyth/MMM-Remote-Control/compare/v3.2.7...HEAD)
9+
10+
**Note:** This release changes the default monitor control commands to support modern Raspberry Pi OS (Wayland). Users can restore the previous behavior via `customCommand` configuration. See the README's "Monitor Control Commands by Display System" section for migration instructions and alternatives for all supported systems.
11+
12+
### Added
13+
14+
- docs: add comprehensive monitor control command reference covering different display systems (Wayland/wlr-randr, X11/Xorg, GNOME/Mutter, CEC, DPMS, legacy vcgencmd) with installation instructions, troubleshooting, and multi-monitor setup guidance
15+
16+
### Changed
17+
18+
- **BREAKING:** refactor: default monitor control commands now use Wayland (`wlr-randr`) instead of deprecated `vcgencmd` to support Raspberry Pi OS Bookworm/Bullseye (Wayland has been the default since 2023)
19+
820
## [3.2.7](https://github.com/jopyth/MMM-Remote-Control/compare/v3.2.6...v3.2.7) - 2025-10-09
921

1022
### Added

README.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,169 @@ Depending on your installation, some `shell` commands used by this module are no
261261
}
262262
```
263263
264+
#### Monitor Control Commands by Display System
265+
266+
**Since version 4.0.0**, the default monitor control commands have changed to support **Wayland** (the default display server in Raspberry Pi OS since Bookworm (released 2023)). If you're using a different setup or experiencing issues, configure the appropriate commands for your system:
267+
268+
##### Wayland (Default - Raspberry Pi OS Bookworm/Bullseye)
269+
270+
**Default commands** (no configuration needed):
271+
272+
```js
273+
customCommand: {
274+
monitorOnCommand: 'wlr-randr --output HDMI-A-1 --on',
275+
monitorOffCommand: 'wlr-randr --output HDMI-A-1 --off',
276+
monitorStatusCommand: 'wlr-randr | grep -q "Enabled: yes" && echo "true" || echo "false"'
277+
}
278+
```
279+
280+
**Note:** You may need to install `wlr-randr` first:
281+
282+
```bash
283+
sudo apt-get install wlr-randr
284+
```
285+
286+
To find your correct output name (might be `HDMI-A-2`, `HDMI-1`, etc.), run:
287+
288+
```bash
289+
wlr-randr
290+
```
291+
292+
If `wlr-randr` doesn't work without specifying the display, try setting the `WAYLAND_DISPLAY` environment variable:
293+
294+
```js
295+
customCommand: {
296+
monitorOnCommand: 'WAYLAND_DISPLAY="wayland-1" wlr-randr --output HDMI-A-1 --on',
297+
monitorOffCommand: 'WAYLAND_DISPLAY="wayland-1" wlr-randr --output HDMI-A-1 --off',
298+
monitorStatusCommand: 'WAYLAND_DISPLAY="wayland-1" wlr-randr | grep -q "Enabled: yes" && echo "true" || echo "false"'
299+
}
300+
```
301+
302+
##### X11 / Xorg
303+
304+
For systems using X11 (older Raspberry Pi OS or desktop Linux):
305+
306+
```js
307+
customCommand: {
308+
monitorOnCommand: 'xrandr --output HDMI-1 --auto',
309+
monitorOffCommand: 'xrandr --output HDMI-1 --off',
310+
monitorStatusCommand: 'xrandr | grep "HDMI-1 connected" | grep -q " [0-9]" && echo "true" || echo "false"'
311+
}
312+
```
313+
314+
**Alternative with explicit display** (use if the above doesn't work):
315+
316+
```js
317+
customCommand: {
318+
monitorOnCommand: 'xrandr -d :0 --output HDMI-1 --auto',
319+
monitorOffCommand: 'xrandr -d :0 --output HDMI-1 --off',
320+
monitorStatusCommand: 'xrandr -d :0 --listmonitors | grep -v "Monitors: 0" && echo "true" || echo "false"'
321+
}
322+
```
323+
324+
To find your output name, run:
325+
326+
```bash
327+
xrandr | grep " connected"
328+
```
329+
330+
Common output names: `HDMI-1`, `HDMI-2`, `DP-1`, `eDP-1`
331+
332+
##### Legacy vcgencmd (Raspberry Pi OS Buster and older)
333+
334+
If you're running an older Raspberry Pi OS version where `vcgencmd` still works:
335+
336+
```js
337+
customCommand: {
338+
monitorOnCommand: 'vcgencmd display_power 1',
339+
monitorOffCommand: 'vcgencmd display_power 0',
340+
monitorStatusCommand: 'vcgencmd display_power -1'
341+
}
342+
```
343+
344+
**Note:** `vcgencmd display_power` has been deprecated and may not work on recent Raspberry Pi OS versions.
345+
346+
##### CEC (HDMI-CEC capable displays)
347+
348+
For displays that support HDMI-CEC control:
349+
350+
```js
351+
customCommand: {
352+
monitorOnCommand: 'echo "on 0" | cec-client -s -d 1',
353+
monitorOffCommand: 'echo "standby 0" | cec-client -s -d 1',
354+
monitorStatusCommand: 'echo "pow 0" | cec-client -s -d 1 | grep -q "power status: on" && echo "true" || echo "false"'
355+
}
356+
```
357+
358+
Install `cec-client`:
359+
360+
```bash
361+
sudo apt-get install cec-utils
362+
```
363+
364+
##### DPMS (Generic Linux)
365+
366+
For generic Linux systems with DPMS support:
367+
368+
```js
369+
customCommand: {
370+
monitorOnCommand: 'xset dpms force on',
371+
monitorOffCommand: 'xset dpms force off',
372+
monitorStatusCommand: 'xset q | grep -q "Monitor is On" && echo "true" || echo "false"'
373+
}
374+
```
375+
376+
##### GNOME/Mutter (Debian 13 Trixie and newer)
377+
378+
For systems using GNOME/Mutter display server (like Debian 13 Trixie):
379+
380+
```js
381+
customCommand: {
382+
monitorOnCommand: 'busctl --user set-property org.gnome.Mutter.DisplayConfig /org/gnome/Mutter/DisplayConfig org.gnome.Mutter.DisplayConfig PowerSaveMode i 0',
383+
monitorOffCommand: 'busctl --user set-property org.gnome.Mutter.DisplayConfig /org/gnome/Mutter/DisplayConfig org.gnome.Mutter.DisplayConfig PowerSaveMode i 1',
384+
monitorStatusCommand: 'busctl --user get-property org.gnome.Mutter.DisplayConfig /org/gnome/Mutter/DisplayConfig org.gnome.Mutter.DisplayConfig PowerSaveMode | grep -q "i 0" && echo "true" || echo "false"'
385+
}
386+
```
387+
388+
##### Troubleshooting Monitor Control
389+
390+
If monitor control doesn't work:
391+
392+
1. **Verify your display server:**
393+
394+
```bash
395+
echo $XDG_SESSION_TYPE # Should show 'wayland' or 'x11'
396+
```
397+
398+
2. **Switch display server if needed:** On Raspberry Pi OS, you can switch between Wayland and X11:
399+
400+
```bash
401+
sudo raspi-config
402+
# Navigate to: Advanced Options -> Wayland -> Select X11 or Wayland -> Reboot
403+
```
404+
405+
3. **Test commands manually:** Run the command directly in the terminal to ensure it works before adding it to the config.
406+
407+
4. **Check output names:** Display output names vary by system. Use `wlr-randr` (Wayland) or `xrandr` (X11) to find the correct name.
408+
409+
For **Wayland**:
410+
411+
```bash
412+
wlr-randr
413+
```
414+
415+
For **X11**:
416+
417+
```bash
418+
xrandr -d :0 # or just: xrandr
419+
```
420+
421+
5. **Multi-monitor setups:** If you have multiple HDMI outputs (like Raspberry Pi 4/5), make sure to specify the correct output (e.g., `HDMI-A-1` vs `HDMI-A-2`).
422+
423+
6. **Permissions:** Some commands may require additional permissions or group membership (e.g., `video` group for CEC).
424+
425+
7. **See the discussion:** For more solutions and community help, check [Issue #288](https://github.com/Jopyth/MMM-Remote-Control/issues/288).
426+
264427
### Custom Classes
265428
266429
You probably wanna hide or show some modules at the same time, right? It's everything that we want this module for, of course.

node_helper.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,13 +649,13 @@ module.exports = NodeHelper.create({
649649
];
650650
const monitorOnCommand = this.initialized && "monitorOnCommand" in this.thisConfig.customCommand
651651
? this.thisConfig.customCommand.monitorOnCommand
652-
: "vcgencmd display_power 1";
652+
: "wlr-randr --output HDMI-A-1 --on";
653653
const monitorOffCommand = this.initialized && "monitorOffCommand" in this.thisConfig.customCommand
654654
? this.thisConfig.customCommand.monitorOffCommand
655-
: "vcgencmd display_power 0";
655+
: "wlr-randr --output HDMI-A-1 --off";
656656
const monitorStatusCommand = this.initialized && "monitorStatusCommand" in this.thisConfig.customCommand
657657
? this.thisConfig.customCommand.monitorStatusCommand
658-
: "vcgencmd display_power -1";
658+
: "wlr-randr | grep -q 'Enabled: yes' && echo 'true' || echo 'false'";
659659
switch (action) {
660660
case "MONITORSTATUS": exec(monitorStatusCommand, opts, (error, stdout, stderr) => {
661661
status = offArr.indexOf(stdout.trim()) !== -1

0 commit comments

Comments
 (0)