#!/bin/bash # jmri-gui — launch JMRI GUI over SSH -X (X11 forwarding) # Managed by Ansible — do not edit manually. # # Usage (connect as jmri user): # ssh -X jmri@main-street-station jmri-gui panelpro # ssh -X jmri@main-street-station jmri-gui decoderpro # ssh -X jmri@main-street-station jmri-gui status # # ~/.ssh/config recommended: # Host main-street-station # User jmri # ForwardX11 yes set -euo pipefail JMRI_DIR="{{ jmri_install_dir }}" JMRI_PROFILE="{{ jmri_profile_id }}" JMRI_SERVICE="jmri.service" MONITOR_SERVICE="jmri-monitor.service" usage() { echo "Usage: jmri-gui " exit 1 } check_display() { if [ -z "${DISPLAY:-}" ]; then echo "ERROR: No DISPLAY set. Connect with: ssh -X jmri@main-street-station" exit 1 fi } status() { echo "=== JMRI daemon ===" systemctl status "$JMRI_SERVICE" --no-pager -l 2>&1 | head -8 echo "" echo "=== Layout monitor ===" systemctl status "$MONITOR_SERVICE" --no-pager -l 2>&1 | head -5 } launch() { local app="$1" local binary case "$app" in panelpro) binary="PanelPro" ;; decoderpro) binary="DecoderPro" ;; *) usage ;; esac check_display # Stop the daemon if running if systemctl is-active --quiet "$JMRI_SERVICE" 2>/dev/null; then echo "Stopping JMRI daemon..." sudo systemctl stop "$JMRI_SERVICE" fi echo "Launching $binary (profile: $JMRI_PROFILE)..." echo "Close the window to return to daemon mode." echo "" # SSH sets DISPLAY to localhost:N (TCP) — translate to unix socket form # so Java's AWT xauth lookup matches the forwarded cookie. export DISPLAY=$(echo "$DISPLAY" | sed 's/localhost:/:/') # Force AWT out of headless mode export JMRI_OPTIONS="-Djava.awt.headless=false" # Run directly — we are already the jmri user, DISPLAY is set by SSH "$JMRI_DIR/$binary" --profile="$JMRI_PROFILE" echo "" echo "$binary closed." # 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 — restarting JMRI daemon." sudo systemctl start "$JMRI_SERVICE" else echo "Layout is OFF — JMRI daemon will not restart." fi fi } case "${1:-}" in panelpro|decoderpro) launch "$1" ;; status) status ;; *) usage ;; esac