Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| hardware:baby-mirror [2026/07/26 23:34] – Sparky | hardware:baby-mirror [2026/08/25 19:17] (current) – Sparky | ||
|---|---|---|---|
| Line 3: | Line 3: | ||
| The Baby Mirror is a [MagicMirror²](https:// | The Baby Mirror is a [MagicMirror²](https:// | ||
| a Raspberry Pi driving a monitor mounted behind one-way glass. It was donated to | a Raspberry Pi driving a monitor mounted behind one-way glass. It was donated to | ||
| - | DMA by / | + | DMA by / |
| the space, including a feed of community quotes. | the space, including a feed of community quotes. | ||
| Line 11: | Line 11: | ||
| chest. | chest. | ||
| - | ## Hardware | + | ## Hardware |
| - | - **Board:** Raspberry Pi 3B+ | + | - **Board:** Raspberry Pi 3B+ (1 GB RAM) |
| - **Display: | - **Display: | ||
| - | - **OS image:** the original /dev/hack MagicMirror image (the Pi was *not* | + | - **OS: |
| - | reimaged when it was donated, so paths and setup match the /dev/hack build) | + | - **MagicMirror: |
| + | - **Networking: | ||
| - | ## Access | + | Note that the Pi has been updated since it was donated. It is no longer running |
| + | the original /dev/hack image, so do not assume the stock /dev/hack layout or | ||
| + | tooling. Paths and service setup are documented below and were confirmed on the | ||
| + | device on 2026-08-25. | ||
| - | - **Hostname (SSH):** `smartmirror.user.dma.computer` | + | ## Finding |
| - | - **SSH user:** `localadmin` | + | |
| - | - **Password: | + | |
| - | the Baby Mirror / `smartmirror` entry there. *(Do not paste credentials | + | |
| - | page, the wiki is public.)* | + | |
| The mirror is on the DMA **user VLAN** (the `dma.space/ | The mirror is on the DMA **user VLAN** (the `dma.space/ | ||
| - | must be on that network to reach it. Its IP is assigned by DHCP and changes, | + | must be on that network to reach it. Its address comes from DHCP and changes. |
| - | connect by hostname, | + | |
| + | **The hostname does not resolve.** `smartmirror.user.dma.computer` will not | ||
| + | resolve even when you are on the user VLAN, because every VLAN's DHCP hands out | ||
| + | public DNS (1.1.1.1 and 1.0.0.1) and the router does not run an internal | ||
| + | resolver. Do not rely on the hostname. mDNS (`smartmirror.local`) did not answer | ||
| + | either when this was last checked. | ||
| + | |||
| + | To find its current address, use one of: | ||
| + | |||
| + | 1. The router' | ||
| + | 2. A sweep of the user VLAN, then look for a host answering SSH with a Debian | ||
| + | | ||
| + | 3. A keyboard on the Pi itself and `hostname -I`. | ||
| + | |||
| + | ## Access | ||
| + | |||
| + | - **SSH user:** `localadmin` | ||
| + | - **Password: | ||
| + | `smartmirror` item. That item lived in a personal vault until 2026-08-24 and | ||
| + | is now shared to the org, so if you cannot find it, check that you are looking | ||
| + | at the org vault. *(Do not paste credentials on this page, the wiki is | ||
| + | public.)* | ||
| ``` | ``` | ||
| - | ssh localadmin@smartmirror.user.dma.computer | + | ssh localadmin@<ip> |
| ``` | ``` | ||
| Line 42: | Line 63: | ||
| ``` | ``` | ||
| - | ## How MagicMirror is managed | + | All three were confirmed correct on 2026-08-25. |
| - | MagicMirror runs as a **systemd user service** under the `localadmin` account | + | ## Console access |
| - | (not pm2, not a desktop autostart file, note this differs from the stock | + | |
| - | /dev/hack docs, so confirm the unit name on the device). | + | |
| - | Find the service name and check its status: | + | If the mirror is off the network, you can get a local console with a USB |
| + | keyboard: | ||
| + | |||
| + | - **Ctrl+Alt+F2** switches to a text console. | ||
| + | - **Ctrl+Alt+F7** switches back to the MagicMirror display. | ||
| + | |||
| + | Two things to know before you rely on this. The console keymap is not US and has | ||
| + | dead keys, so quotes and symbols are hard to type correctly, and `loadkeys` | ||
| + | cannot help because `/ | ||
| + | quotes or a password is much easier over SSH. Also remember to log out of the | ||
| + | console when you are done, since the space is shared. | ||
| + | |||
| + | ## If the mirror is on but shows no data | ||
| + | |||
| + | A module reporting "no internet connection" | ||
| + | dropped off wifi. This happened on 2026-08-25 and the device had been offline | ||
| + | long enough that nobody noticed. | ||
| + | |||
| + | Wifi is managed by **NetworkManager**, | ||
| + | There is no `/ | ||
| + | `wpa_cli` network blocks will not work, because NetworkManager owns the | ||
| + | supplicant. | ||
| + | |||
| + | From a console on the Pi, the fix that worked was simply restarting the service: | ||
| ```bash | ```bash | ||
| - | # verify on device, service name is a placeholder until confirmed | + | sudo systemctl |
| - | systemctl | + | |
| - | systemctl --user status < | + | |
| ``` | ``` | ||
| - | Restart it (e.g. after editing the config): | + | It reconnected and picked up a DHCP lease immediately. If that is not enough: |
| ```bash | ```bash | ||
| - | systemctl | + | nmcli device status |
| + | sudo nmcli device wifi rescan | ||
| + | nmcli device wifi list | ||
| + | sudo nmcli --ask device wifi connect dma.space/ | ||
| ``` | ``` | ||
| - | View logs: | + | `nmcli device wifi connect` can report that the network cannot be found when the |
| + | scan cache is stale, so always rescan first. Using `--ask` prompts for the | ||
| + | password instead of taking it on the command line, which avoids both shell | ||
| + | quoting and the console keymap problem. | ||
| + | |||
| + | ## How MagicMirror is managed | ||
| + | |||
| + | MagicMirror runs as a **systemd user service** under the `localadmin` account. | ||
| + | The unit lives at `~/ | ||
| + | boot, and starts `/ | ||
| + | the `/dev/hack` start script are not alternatives to each other; the unit runs | ||
| + | the script. | ||
| ```bash | ```bash | ||
| - | journalctl | + | systemctl |
| + | systemctl | ||
| ``` | ``` | ||
| - | > **Verify on device:** the exact service name and that MagicMirror really is a | + | **Logs.** `journalctl |
| - | > `systemctl | + | journal files were found", |
| - | > desktop autostart file at `~/.config/ | + | either of these instead: |
| - | > `~/ | + | |
| + | ```bash | ||
| + | systemctl --user | ||
| + | sudo journalctl _UID=1000 -n 40 --no-pager | ||
| + | ``` | ||
| ## Configuration | ## Configuration | ||
| - | MagicMirror config lives at (per the /dev/hack image, verify on device): | + | MagicMirror config lives at: |
| ``` | ``` | ||
| Line 82: | Line 141: | ||
| Modules are configured in the `modules: [ ... ]` array in that file. Installed | Modules are configured in the `modules: [ ... ]` array in that file. Installed | ||
| - | modules live under `/ | + | modules live under `/ |
| - | `config.js`, restart | + | |
| + | **Always back up and validate before restarting.** A malformed | ||
| + | MagicMirror from starting and leaves | ||
| + | |||
| + | ```bash | ||
| + | cd / | ||
| + | cp config.js config.js.bak-$(date +%F) | ||
| + | # edit, then check that it parses before restarting: | ||
| + | node -e ' | ||
| + | systemctl --user restart magicmirror.service | ||
| + | ``` | ||
| + | |||
| + | To roll back: | ||
| + | |||
| + | ```bash | ||
| + | cp config.js.bak-< | ||
| + | systemctl --user restart magicmirror.service | ||
| + | ``` | ||
| ## Displaying the community quotes feed | ## Displaying the community quotes feed | ||
| - | Quotes | + | Quotes |
| - | [`newsfeed`](https://docs.magicmirror.builders/modules/newsfeed.html) module, | + | |
| - | pointed at the DMA quotes RSS feed. | + | ``` |
| + | https://portal.dma.space/api/feeds/ | ||
| + | ``` | ||
| + | |||
| + | The feed is public and needs no token. Confirm the mirror can reach it before | ||
| + | relying on it, and **test with GET, not HEAD**. The endpoint is GET-only and | ||
| + | `curl -I` returns 405 even when the feed is perfectly healthy: | ||
| + | |||
| + | ```bash | ||
| + | curl -sS -o /dev/null -w ' | ||
| + | ``` | ||
| - | Add (or edit) an entry in the `modules` array in `config.js`: | + | The display uses MagicMirror' |
| + | [`newsfeed`](https:// | ||
| + | This is the block currently | ||
| ```js | ```js | ||
| { | { | ||
| - | | + | |
| - | position: " | + | position: " |
| - | config: { | + | config: { |
| - | feeds: [ | + | feeds: [ |
| - | { | + | { |
| - | title: "DMA Quotes", | + | title: "DMA Quotes", |
| - | url: " | + | url: " |
| - | }, | + | } |
| - | ], | + | ], |
| - | showSourceTitle: | + | showSourceTitle: |
| - | showPublishDate: | + | showPublishDate: |
| - | showDescription: | + | showDescription: |
| - | }, | + | } |
| - | } | + | }, |
| ``` | ``` | ||
| - | Then restart | + | `showDescription` is deliberately `false`. Each entry carries |
| + | its `< | ||
| + | to show. For the same reason, do not add `ignoreOldItems`: | ||
| + | infrequently and the newest entry is often weeks old, so filtering by age would | ||
| + | empty the bar. | ||
| - | > **Reachability note: | + | The large centred text on the mirror is the separate `compliments` module, not |
| - | > mirror is on the user VLAN. Before relying on this, confirm the mirror can | + | the quotes feed. |
| - | > actually reach the feed from that VLAN: | + | |
| - | > | + | |
| - | > ```bash | + | |
| - | > curl -sI https://< | + | |
| - | > ``` | + | |
| - | > | + | |
| - | > If it can't reach the monolith, the feed URL needs to be exposed on a path the | + | |
| - | > user VLAN can reach. | + | |
| ## Editing safely | ## Editing safely | ||
| This is a **production device** on the space' | This is a **production device** on the space' | ||
| - | changes, | + | changes, |
| - | mirror comes up blank after a change, | + | service to apply. If the mirror comes up blank after a change, |
| - | `config.js` will stop MagicMirror from starting. | + | backup and restart. |
| + | |||
| + | ## Known issues | ||
| + | |||
| + | - The wifi dropout described | ||
| + | | ||
| + | If the mirror goes dark again, check wifi first. | ||