<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pm2 on K-Life Hack | Systems Architecture &amp; DevOps</title><link>https://klifehack.com/en/tags/pm2/</link><description>Recent content in Pm2 on K-Life Hack | Systems Architecture &amp; DevOps</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 25 Aug 2026 10:10:42 +0900</lastBuildDate><atom:link href="https://klifehack.com/en/tags/pm2/index.xml" rel="self" type="application/rss+xml"/><item><title>Auto-Start Control, Screen Rotation, and Touch Coordinate System Calibration in MagicMirror²</title><link>https://klifehack.com/en/p/magicmirror-pm2-systemd-xrandr-xinput-setup/</link><pubDate>Tue, 25 Aug 2026 10:10:42 +0900</pubDate><guid>https://klifehack.com/en/p/magicmirror-pm2-systemd-xrandr-xinput-setup/</guid><description>&lt;p&gt;In the operation of embedded displays and smart mirror platforms, automatic process recovery at OS boot and synchronous control of screen display are critical. If a front-end application launches before the network interface is enabled, asynchronous requests to external RSS feeds or APIs may fail, posing a risk of rendering errors. Furthermore, when installing an LCD panel in portrait orientation or inverted (upside down), changing only the display output (&lt;code&gt;xrandr&lt;/code&gt;) leaves the input coordinate system of the touch panel (&lt;code&gt;xinput&lt;/code&gt;) out of sync, causing the operation axes to invert.&lt;/p&gt;&#10;&lt;p&gt;This article outlines the design of a delayed start sequence combining PM2 and Systemd, display rotation settings, calibration of the touch Coordinate Transformation Matrix, and module code modification procedures.&lt;/p&gt;&#10;&lt;h2 id="1-process-auto-start-and-system-daemon-configuration"&gt;1. Process Auto-Start and System Daemon Configuration&#10;&lt;/h2&gt;&lt;p&gt;To ensure application process liveness checks and automatic recovery upon OS reboot, a management configuration using PM2 and Systemd is introduced.&lt;/p&gt;&#10;&lt;h3 id="global-installation-and-initialization-of-pm2"&gt;Global Installation and Initialization of PM2&#10;&lt;/h3&gt;&lt;p&gt;Install PM2 to handle process management in the Node.js environment.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo npm install -g pm2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To register PM2 as an OS startup daemon, execute the following command and run the generated Systemd registration command in the terminal.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pm2 startup&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="creating-a-delayed-launch-script-mmsh"&gt;Creating a Delayed Launch Script (mm.sh)&#10;&lt;/h3&gt;&lt;p&gt;To prevent the application from starting before a network connection is established, create an execution script with a buffer delay in the user&amp;rsquo;s home directory.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ~&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nano mm.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The internal implementation of the script is as follows. Inserting &lt;code&gt;sleep 10&lt;/code&gt; waits for the acquisition of the Wi-Fi/Ethernet IP address to complete, while &lt;code&gt;DISPLAY=:0&lt;/code&gt; explicitly binds the output target of the X11 session.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sleep &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ./MagicMirror&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DISPLAY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;:0 npm start&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Grant execution permissions.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chmod +x mm.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="saving-process-state-and-systemd-control"&gt;Saving Process State and Systemd Control&#10;&lt;/h3&gt;&lt;p&gt;Persist the process state started with PM2.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pm2 save&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Commands to enable or disable auto-start as a Systemd service are as follows.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Enable startup&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl enable magicmirror.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Disable startup&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl disable magicmirror.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="2-display-power-control-and-static-syntax-analysis"&gt;2. Display Power Control and Static Syntax Analysis&#10;&lt;/h2&gt;&lt;p&gt;In a continuously operating signage environment, it is necessary to prevent OS default screensavers and power-saving blackouts.&lt;/p&gt;&#10;&lt;h3 id="disabling-sleep-features"&gt;Disabling Sleep Features&#10;&lt;/h3&gt;&lt;p&gt;Install &lt;code&gt;xscreensaver&lt;/code&gt; and change the screensaver and display blanking functions to &amp;ldquo;Disable Screen Saver&amp;rdquo; via the GUI settings screen or configuration file.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install xscreensaver&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="syntax-check-of-configuration-file-configjs"&gt;Syntax Check of Configuration File (config.js)&#10;&lt;/h3&gt;&lt;p&gt;Syntax errors in &lt;code&gt;config/config.js&lt;/code&gt; (unclosed brackets, missing or extra commas) cause runtime errors. Before deployment, pass the source code through a static analysis tool (such as JSHint) to verify syntax correctness.&lt;/p&gt;&#10;&lt;h2 id="3-display-and-touch-coordinate-synchronization-via-xrandr-and-xinput"&gt;3. Display and Touch Coordinate Synchronization via xrandr and xinput&#10;&lt;/h2&gt;&lt;p&gt;When changing the physical display layout, the coordinate transformation matrix of the X11 display output (&lt;code&gt;xrandr&lt;/code&gt;) and the touch input device (&lt;code&gt;xinput&lt;/code&gt;) must be synchronized.&lt;/p&gt;&#10;&lt;h3 id="rotating-standard-hdmi-output-xrandr"&gt;Rotating Standard HDMI Output (xrandr)&#10;&lt;/h3&gt;&lt;p&gt;Command parameters for rotation settings on the &lt;code&gt;HDMI-1&lt;/code&gt; device.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Normal display (landscape)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output HDMI-1 --rotate normal&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Rotate 90 degrees left (portrait)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output HDMI-1 --rotate left&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Rotate 90 degrees right (portrait)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output HDMI-1 --rotate right&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Rotate 180 degrees (inverted)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output HDMI-1 --rotate inverted&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="touch-panel-coordinate-system-calibration-xinput"&gt;Touch Panel Coordinate System Calibration (xinput)&#10;&lt;/h3&gt;&lt;p&gt;When using a DSI-connected touch display (e.g., &lt;code&gt;FT5406 memory based driver&lt;/code&gt;), the &lt;code&gt;Coordinate Transformation Matrix&lt;/code&gt; (3x3 matrix) must be calculated and configured to match the screen rotation.&lt;/p&gt;&#10;&lt;h4 id="1-normal-orientation-normal"&gt;1. Normal Orientation (normal)&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output DSI-1 --rotate normal&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xinput --set-prop &lt;span style="color:#e6db74"&gt;&amp;#34;FT5406 memory based driver&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Coordinate Transformation Matrix&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="2-90-degree-counterclockwise-rotation-left"&gt;2. 90-Degree Counterclockwise Rotation (left)&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output DSI-1 --rotate left&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xinput --set-prop &lt;span style="color:#e6db74"&gt;&amp;#34;FT5406 memory based driver&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Coordinate Transformation Matrix&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; -1 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="3-90-degree-clockwise-rotation-right"&gt;3. 90-Degree Clockwise Rotation (right)&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output DSI-1 --rotate right&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xinput --set-prop &lt;span style="color:#e6db74"&gt;&amp;#34;FT5406 memory based driver&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Coordinate Transformation Matrix&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; -1 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="4-180-degree-inverted-orientation-inverted"&gt;4. 180-Degree Inverted Orientation (inverted)&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xrandr --output DSI-1 --rotate inverted&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xinput --set-prop &lt;span style="color:#e6db74"&gt;&amp;#34;FT5406 memory based driver&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Coordinate Transformation Matrix&amp;#34;&lt;/span&gt; -1 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; -1 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="4-source-code-modification-of-mmm-backgroundslideshow-module"&gt;4. Source Code Modification of MMM-BackgroundSlideshow Module&#10;&lt;/h2&gt;&lt;p&gt;This is a refactoring example to disable header text (&amp;ldquo;Picture Info&amp;rdquo;) and image count information (e.g., &amp;ldquo;1 of 10&amp;rdquo;) on the screen for the background slideshow display module &lt;code&gt;MMM-BackgroundSlideshow&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;Target file: &lt;code&gt;MMM-BackgroundSlideshow.js&lt;/code&gt;&lt;/p&gt;&#10;&lt;h3 id="code-before-modification"&gt;Code Before Modification&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;imagecount&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;imageProps&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;push&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;imageIndex&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; of &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;imageList&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;warn&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;prop&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39; is not a valid value for imageInfo. Please check your configuration&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;innerHTML&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;header class=&amp;#34;infoDivHeader&amp;#34;&amp;gt;Picture Info&amp;lt;/header&amp;gt;&amp;#39;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;imageProps&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;idx&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;gt&lt;/span&gt;; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;innerHTML&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;val&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;br/&amp;gt;&amp;#39;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="code-after-modification"&gt;Code After Modification&#10;&lt;/h3&gt;&lt;p&gt;Hiding the UI elements is achieved by commenting out the array push operations and replacing the initial &lt;code&gt;innerHTML&lt;/code&gt; value with an empty string.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;imagecount&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Disable array insertion to hide count information&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// imageProps.push(`${this.imageIndex} of ${this.imageList.length}`);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;warn&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;prop&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39; is not a valid value for imageInfo. Please check your configuration&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Completely remove header text&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;innerHTML&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;imageProps&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;idx&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;gt&lt;/span&gt;; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;innerHTML&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;val&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;br/&amp;gt;&amp;#39;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="5-troubleshooting"&gt;5. Troubleshooting&#10;&lt;/h2&gt;&lt;h3 id="startup-failure-due-to-unbound-display-display-environment-variable-issue"&gt;Startup Failure Due to Unbound Display (DISPLAY Environment Variable Issue)&#10;&lt;/h3&gt;&lt;p&gt;💡 &lt;b&gt;Symptom&lt;/b&gt;: &lt;code&gt;Error: Cannot open display: null&lt;/code&gt; occurs during startup via Systemd or Cron, preventing the Electron window from opening.&lt;/p&gt;&#10;&lt;p&gt;🛠️ &lt;b&gt;Cause&lt;/b&gt;: When executing processes from a non-interactive shell environment, the X11 display environment variable &lt;code&gt;$DISPLAY&lt;/code&gt; is not defined.&lt;/p&gt;&#10;&lt;p&gt;⚠️ &lt;b&gt;Solution&lt;/b&gt;: Explicitly declare &lt;code&gt;export DISPLAY=:0&lt;/code&gt; inside the execution script such as &lt;code&gt;mm.sh&lt;/code&gt; before running the commands.&lt;/p&gt;&#10;&lt;h3 id="touch-panel-axis-mismatch-xinput-matrix-mismatch"&gt;Touch Panel Axis Mismatch (xinput Matrix Mismatch)&#10;&lt;/h3&gt;&lt;p&gt;💡 &lt;b&gt;Symptom&lt;/b&gt;: The screen display switches to vertical orientation, but touching the top of the screen moves the cursor to the right side.&lt;/p&gt;&#10;&lt;p&gt;🛠️ &lt;b&gt;Cause&lt;/b&gt;: Only graphic output rotation via &lt;code&gt;xrandr&lt;/code&gt; was applied, and the transformation matrix on the input kernel driver side was not updated.&lt;/p&gt;&#10;&lt;p&gt;⚠️ &lt;b&gt;Solution&lt;/b&gt;: Confirm the device identifier name with &lt;code&gt;xinput list&lt;/code&gt;, and reapply the &lt;code&gt;Coordinate Transformation Matrix&lt;/code&gt; parameter corresponding to the rotation angle.&lt;/p&gt;&#10;&lt;h2 id="6-system-verification-logs"&gt;6. System Verification Logs&#10;&lt;/h2&gt;&lt;p&gt;An example terminal log verifying process running status, X11 display assignment status, and input device property consistency post-deployment.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pm2 status&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌────┬─────────────────┬─────────────┬─────────┬─────────┬─────────┬────────┬─────┬───────────┬──────────┬──────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├────┼─────────────────┼─────────────┼─────────┼─────────┼─────────┼────────┼─────┼───────────┼──────────┼──────────┤&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 0 │ magicmirror │ default │ 2.25.0 │ fork │ 2104 │ 12m │ 0 │ online │ 1.2% │ 142.5MB │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└────┴─────────────────┴─────────────┴─────────┴─────────┴─────────┴────────┴─────┴───────────┴──────────┴──────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ xrandr --query&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Screen 0: minimum 320 x 200, current 1080 x 1920, maximum 7680 x 7680&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DSI-1 connected primary 1080x1920+0+0 right (normal left inverted right x axis y axis) 154mm x 85mm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1080x1920 60.00*+&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ xinput list-props &amp;#34;FT5406 memory based driver&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Device &amp;#39;FT5406 memory based driver&amp;#39;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;Device Enabled (115):&#9;1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;Coordinate Transformation Matrix (117):&#9;0.000000, 1.000000, 0.000000, -1.000000, 0.000000, 1.000000, 0.000000, 0.000000, 1.000000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="7-lessons-learned"&gt;7. Lessons Learned&#10;&lt;/h2&gt;&lt;p&gt;For stable operation of embedded signage environments, it is critical to comprehensively understand not only the software layer (PM2/Node.js) but also the interdependencies among the OS display subsystem (X11/xrandr) and input device drivers (xinput). In particular, considering race conditions during startup until the network and display server are fully initialized during the design phase significantly mitigates unnecessary reboot issues post-field deployment.&lt;/p&gt;&#10;</description></item></channel></rss>