#!/bin/bash # jmri-gui — launch JMRI GUI on Xpra virtual display # Managed by Ansible — do not edit manually. # # Usage (connect as jmri user): # jmri-gui panelpro Launch PanelPro on Xpra display # jmri-gui decoderpro Launch DecoderPro on Xpra display # jmri-gui status Show service status and attach command # # Then attach from macOS/Linux: # xpra attach ssh://jmri@main-street-station/{{ jmri_xpra_display }} set -euo pipefail JMRI_DIR="{{ jmri_install_dir }}" JMRI_SERVICE="jmri.service" MONITOR_SERVICE="jmri-monitor.service" XPRA_SERVICE="jmri-xpra.service" DISPLAY=":{{ jmri_xpra_display }}" export DISPLAY usage() { echo "Usage: jmri-gui " exit 1 } status() { echo "=== JMRI daemon ===" systemctl status "$JMRI_SERVICE" --no-pager -l 2>&1 | head -8 echo "" echo "=== Xpra display ===" systemctl status "$XPRA_SERVICE" --no-pager -l 2>&1 | head -5 echo "" echo "=== Layout monitor ===" systemctl status "$MONITOR_SERVICE" --no-pager -l 2>&1 | head -5 echo "" echo "To attach: xpra attach ssh://jmri@$(hostname -f)/{{ jmri_xpra_display }}" } launch() { local app="$1" local binary case "$app" in panelpro) binary="PanelPro" ;; decoderpro) binary="DecoderPro" ;; *) usage ;; esac # Ensure Xpra display is running if ! systemctl is-active --quiet "$XPRA_SERVICE" 2>/dev/null; then echo "Starting Xpra display..." sudo systemctl start "$XPRA_SERVICE" sleep 2 fi # Stop the JMRI daemon if running (we're taking over the hardware connections) if systemctl is-active --quiet "$JMRI_SERVICE" 2>/dev/null; then echo "Stopping JMRI daemon..." sudo systemctl stop "$JMRI_SERVICE" fi # Force AWT out of headless mode export JMRI_OPTIONS="-Djava.awt.headless=false" echo "Launching $binary on Xpra display $DISPLAY..." echo "" echo "Attach from your workstation:" echo " xpra attach ssh://jmri@$(hostname -f)/{{ jmri_xpra_display }}" echo "" "$JMRI_DIR/$binary" & echo "$binary launched. Attach with xpra to see windows." echo "" # Restart daemon if layout switch is still on if systemctl is-active --quiet "$MONITOR_SERVICE" 2>/dev/null; then if sudo /opt/jmri-monitor/bin/python3 - <<'EOF' from decora_wifi import DecoraWiFiSession from decora_wifi.models.residential_account import ResidentialAccount import sys session = DecoraWiFiSession() person = session.login("{{ jmri_leviton_email }}", "{{ jmri_leviton_password }}") perms = person.get_residential_permissions() for perm in perms: acct_id = perm.data.get('residentialAccountId') if not acct_id: continue acct = ResidentialAccount(session, acct_id) acct.refresh() for r in acct.get_residences(): for s in r.get_iot_switches(): if s.data.get('name') == '{{ jmri_leviton_switch_name }}': sys.exit(0 if s.data.get('power') == 'ON' else 1) sys.exit(1) EOF then echo "Layout is ON — JMRI daemon will restart when GUI is closed." else echo "Layout is OFF — JMRI daemon will not restart." fi fi } case "${1:-}" in panelpro|decoderpro) launch "$1" ;; status) status ;; *) usage ;; esac