MMM-Remote-Control is a module for MagicMirror² that allows you to use a browser, to quickly shut down your mirror, hide and show modules on your mirror and do other cool stuff.
The website should work fine on any device (desktop, smartphone, tablet, ...).
Since we all want our SD cards to live a long and prosper life we shut down properly every time before unplugging, right?
The module also includes a RESTful API for controlling all aspects of your mirror from other network-enabled devices and controllers--anything that can open a URL. See the API README for more info!
New features:
- 📱 PWA Support: Install the remote control as an app on your smartphone for easy access
- 📷 QR Code Display: Show a QR code on your mirror for instant mobile connection - simply scan and connect!
-
Clone this repository in your
modulesdirectory, and install dependencies:cd ~/MagicMirror/modules git clone https://github.com/Jopyth/MMM-Remote-Control cd MMM-Remote-Control npm ci --omit=dev
The installation will display a sample API key that you can use (optional).
-
Add the module to your
config.jsfile. Note: You must set apositionto display the URL/QR code on the mirror.{ module: 'MMM-Remote-Control', position: 'bottom_left', // Required to show URL/QR code on mirror // you can hide this module afterwards from the remote control itself config: { customCommand: {}, // Optional, See "Using Custom Commands" below showModuleApiMenu: true, // Optional, Enable the Module Controls menu secureEndpoints: true, // Optional, See API/README.md // uncomment any of the lines below if you're gonna use it // customMenu: "custom_menu.json", // Optional, See "Custom Menu Items" below // apiKey: "", // Optional, See API/README.md for details // classes: {}, // Optional, See "Custom Classes" below // QR Code options (new!) // showQRCode: true, // Optional, display QR code for easy mobile access (default: true) // qrCodeSize: 150, // Optional, size of QR code in pixels (default: 150) // qrCodePosition: "below" // Optional: // "below" - Show URL above, QR code below (default) // "above" - Show QR code above, URL below // "replace" - Show only QR code, no URL text } },
-
For security reasons, the MagicMirror² (and therefore the Remote Control) is not reachable externally. To change this, configure
address, andipWhitelistin yourconfig.js(see these lines in the sample config). For example changeaddressto0.0.0.0and add two allowed devices with IP addresses192.168.0.42and192.168.0.50:address : '0.0.0.0', port: 8080, ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.0.42", "::ffff:192.168.0.50"],"
You can also add multiple devices in an IP range (e.g. all devices with
192.168.0.X):ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.0.1/120", "192.168.0.1/24"],
-
Restart MagicMirror².
-
Access the remote interface on http://192.168.xxx.xxx:8080/remote.html (replace with IP address of your RaspberryPi).
Note: PWA installation may require HTTPS. If you experience issues, this feature might only work when MagicMirror² is running under HTTPS. Feedback would be appreciated!
You can install the remote control as an app on your smartphone:
- Open the remote interface in your mobile browser (Chrome/Safari)
- On Android (Chrome): Tap the menu (⋮) → "Install app" or "Add to Home screen"
- On iOS (Safari): Tap Share (□↑) → "Add to Home Screen"
- The remote control will now work like a native app with offline support!
Update this module by navigating into its directory on the command line and using git pull:
cd ~/MagicMirror/modules/MMM-Remote-Control
git pull
npm ci --omit=devYou can check out specific versions in the following way. First look at which versions are available:
cd MagicMirror/modules/MMM-Remote-Control # or wherever you installed the Mirror and the module
git fetch # fetch all tags
git tag # display themThe output should look similar to this:
v1.0.0
v1.1.0
v1.1.1
v1.1.2Then you can checkout that version with, for example git switch --detach v1.0.0, or use git switch master to checkout the most recent version.
Whenever you change the order of modules in config.js or add/remove modules, the indices of the modules change.
Therefore the hidden/shown status of modules might not be correctly applied.
If this happens, simply reconfigure and save it again.
You can call any of the methods provided in the UI directly through a GET request, or a module notification. For example you can use MMM-ModuleScheduler to automatically shutdown your RaspberryPi at a certain time, or integrate it with home automation systems. Or use MMM-Navigate to allow direct actions from your Mirror by using a rotating button.
-
Example for a REST API GET request to trigger a system reboot:
http://192.168.xxx.xxx:8080/api/reboot -
Example to trigger MagicMirror² restart in your module:
this.sendNotification("REMOTE_ACTION", { action: "RESTART" });
See the Examples Guide for more integration examples with MMM-ModuleScheduler, MMM-Navigate, Home Assistant, and more.
| Action | Description |
|---|---|
| SHUTDOWN | Shutdown your RaspberryPi |
| REBOOT | Restart your RaspberryPi |
| MONITORON | Switch your display on. Also sends a "USER_PRESENCE": true notification. |
| MONITOROFF | Switch your display off. Also sends a "USER_PRESENCE": false notification. |
| MONITORTOGGLE | Toggle the display on or off (with respective "USER_PRESENCE" notification. |
| MONITORSTATUS | Report back the monitor status (on or off) |
| Action | Description |
|---|---|
| RESTART | Restart MagicMirror² (Electron relaunch or clean process exit for process managers like systemd/PM2/Docker) |
| STOP | Stop MagicMirror² without restarting (exits with error code, process managers won't auto-restart) |
| REFRESH | Refresh mirror page |
| UPDATE | Update MagicMirror² and any of it's modules |
| SAVE | Save the current configuration (show and hide status of modules, and brightness), will be applied after the mirror starts |
| BRIGHTNESS | Change mirror brightness, with the new value specified by value. 100 equals the default (full brightness), possible range is between 0 (black) and 100. |
| Action | Description |
|---|---|
| MINIMIZE | Minimize the browser window. Warning: Cannot be undone via remote (Wayland limitation). |
| TOGGLEFULLSCREEN | Toggle fullscreen mode on and off. |
| DEVTOOLS | Open the DevTools console window. |
| Action | Description |
|---|---|
| HIDE | Hide a module, with the name (or identifier--see MODULE_DATA action) specified by module in the payload. You can also send module: "all" to hide all modules. |
| SHOW | Show a module (see above for how to specify which one). |
| TOGGLE | Toggle a module's visibility (see above for how to specify which one). |
| FORCE | Force a module to show (see above for how to specify which one). |
| MODULE_DATA | Returns a JSON format of the data displayed in the UI, including all valid identifiers for the HIDE and SHOW action. |
| Action | Description |
|---|---|
| SHOW_ALERT | Show Default Alert/Notification |
| HIDE_ALERT | Hide Default Alert/Notification |
| USER_PRESENCE | Will send a notification "USER_PRESENCE" = true or false (according to "value" to all other modules. See examples above |
| NOTIFICATION | To send a notification to all modules, see the example in the API README |
| DELAYED | Send any of the above nested inside a "DELAYED" call to delay the action. Default is 10s. See Delayed Actions below. |
The response will be in the JSON format, here is an example:
{
"moduleData": [
{ "hidden": false, "name": "alert", "identifier": "module_0_alert" },
{
"hidden": true,
"name": "clock",
"identifier": "module_1_clock",
"position": "bottom_right"
},
{
"hidden": false,
"name": "weather",
"identifier": "module_2_weather",
"position": "top_right"
}
],
"brightness": 40,
"settingsVersion": 1
}You can delay an action by sending the notification nested inside of a "DELAYED" notification. Below is an example of turning off the monitor in 60s.
this.sendSocketNotification("REMOTE_ACTION", {
action: "DELAYED",
did: "SOME_UNIQUE_ID", // Optional; Some string, in case you want to cancel later.
timeout: 60, // Optional; Default 10s
abort: false, // Optional; send true to cancel an existing timer
query: {
action: "MONITOROFF"
}
});Can also be used with the API by adding /delay?timeout=10s&did=something to some routes.
Override default shell commands for shutdown, reboot, and monitor control. See the Custom Commands Guide for details.
Monitor not turning on/off? The default
vcgencmdcommands don't work on newer Raspberry Pi OS (Bookworm+). See the Monitor Control Guide for Wayland, X11, CEC, and other options.
Group modules to show/hide together with a single action. See the Classes Guide for details.
classes: {
"Day Mode": {
show: ["clock", "weather"],
hide: ["screensaver"],
},
}Example of Classes in the web interface:
Create custom buttons in the web interface. See the Custom Menus Guide for details.
Copy custom_menu.example.json to your MagicMirror config/ directory, rename it, and add to your config:
customMenu: "custom_menu.json",For detailed documentation, see the docs/guide/ directory or the following links:
- Configuration - All config options
- Monitor Control - Wayland, X11, CEC commands
- Custom Commands - Shell command overrides
- Custom Menus - Build custom UI buttons
- Classes - Group modules together
- Examples - Integration with other modules
- FAQ - Troubleshooting
For contributing to this repository, please see the CONTRIBUTING.md file.
See tests/README.md for test setup, commands, and the roadmap. Quick commands:
- Lint & formatting:
node --run lint - Spell checking:
node --run test:spelling - Unit tests (Node built-in):
node --run test:unit - Coverage (c8):
node --run test:coverage
This project is licensed under the MIT License - see the LICENSE file for details.
All notable changes to this project will be documented in the CHANGELOG.md file.




