Adding restart watchdog and moving to i0t.app
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Stream Deck privileged command helper
|
||||
Documentation=https://github.com/WoodardDigital/streamdeck-go
|
||||
Documentation=https://git.i0t.app/WoodardDigital/streamdeck-go
|
||||
# Start before the user session so the socket is ready when streamdeck-go starts.
|
||||
Before=graphical.target
|
||||
|
||||
|
||||
8
systemd/streamdeck-go-watchdog.service
Normal file
8
systemd/streamdeck-go-watchdog.service
Normal file
@@ -0,0 +1,8 @@
|
||||
[Unit]
|
||||
Description=Stream Deck watchdog (one-shot)
|
||||
Documentation=https://git.i0t.app/WoodardDigital/streamdeck-go
|
||||
After=streamdeck-go.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=%h/.local/bin/streamdeck-go-watchdog
|
||||
135
systemd/streamdeck-go-watchdog.sh
Normal file
135
systemd/streamdeck-go-watchdog.sh
Normal file
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env bash
|
||||
# streamdeck-go watchdog — runs every 30s via systemd timer (Linux) or launchd
|
||||
# StartInterval (macOS).
|
||||
#
|
||||
# Why this exists: when the Stream Deck is unplugged and replugged, the daemon's
|
||||
# in-process reconnect logic does not always notice. On Linux, hidraw can keep
|
||||
# returning read timeouts on the now-stale fd instead of surfacing an error, so
|
||||
# the "3 consecutive errors → reconnect" path never triggers, and the service
|
||||
# manager still reports the service as active even though the device is
|
||||
# unreachable.
|
||||
#
|
||||
# Strategy: track the device's transient USB address (Linux: bus:device,
|
||||
# macOS: Location ID). When it changes (unplug/replug) or the service is
|
||||
# inactive while a device is present, restart the service.
|
||||
set -euo pipefail
|
||||
|
||||
# Stream Deck product IDs we support (see internal/device/streamdeck.go).
|
||||
PIDS_RE="00ba|006c|006d"
|
||||
|
||||
OS="$(uname -s)"
|
||||
|
||||
case "$OS" in
|
||||
Linux)
|
||||
STATE_DIR="${XDG_RUNTIME_DIR:-/tmp}"
|
||||
;;
|
||||
Darwin)
|
||||
# No XDG_RUNTIME_DIR on macOS; use the user-private temp dir.
|
||||
STATE_DIR="${TMPDIR:-/tmp}"
|
||||
;;
|
||||
*)
|
||||
echo "watchdog: unsupported OS: $OS" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
STATE_FILE="$STATE_DIR/streamdeck-go-watchdog.state"
|
||||
|
||||
# Print a transient identifier for the first matching Stream Deck on the USB
|
||||
# bus, or empty if none is present. The identifier must change across
|
||||
# unplug/replug so we can detect it.
|
||||
current_addr() {
|
||||
case "$OS" in
|
||||
Linux)
|
||||
# "Bus 003 Device 052: ID 0fd9:00ba ..." → "003:052"
|
||||
lsusb 2>/dev/null | awk -v pids="$PIDS_RE" '
|
||||
$0 ~ ("ID 0fd9:(" pids ")") {
|
||||
gsub(":", "", $4)
|
||||
print $2 ":" $4
|
||||
exit
|
||||
}
|
||||
'
|
||||
;;
|
||||
Darwin)
|
||||
# system_profiler entry per device:
|
||||
# Stream Deck XL:
|
||||
# Product ID: 0x00ba
|
||||
# Vendor ID: 0x0fd9 (Elgato ...)
|
||||
# ...
|
||||
# Location ID: 0x14140000 / 5
|
||||
# The trailing "/ N" is the bus address — it changes on replug.
|
||||
system_profiler SPUSBDataType 2>/dev/null | awk -v pids="$PIDS_RE" '
|
||||
/^[[:space:]]*Product ID:/ { pid = $3 }
|
||||
/^[[:space:]]*Vendor ID:/ { vid = $3 }
|
||||
/^[[:space:]]*Location ID:/ {
|
||||
sub(/^[[:space:]]*Location ID:[[:space:]]*/, "")
|
||||
if (vid == "0x0fd9" && pid ~ ("^0x(" pids ")$")) {
|
||||
print
|
||||
exit
|
||||
}
|
||||
}
|
||||
'
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Is the streamdeck-go service currently active?
|
||||
service_active() {
|
||||
case "$OS" in
|
||||
Linux)
|
||||
systemctl --user is-active --quiet streamdeck-go.service
|
||||
;;
|
||||
Darwin)
|
||||
# launchctl list prints "PID Status Label". A PID of "-" means
|
||||
# the agent is loaded but not running.
|
||||
local line
|
||||
line="$(launchctl list 2>/dev/null | awk '$3 == "com.woodarddigital.streamdeck-go" { print $1 }')"
|
||||
[[ -n "$line" && "$line" != "-" ]]
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
restart_service() {
|
||||
case "$OS" in
|
||||
Linux)
|
||||
systemctl --user restart streamdeck-go.service
|
||||
;;
|
||||
Darwin)
|
||||
# kickstart -k stops and restarts; works whether or not it's running.
|
||||
launchctl kickstart -k "gui/$(id -u)/com.woodarddigital.streamdeck-go"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
prev=""
|
||||
[[ -f "$STATE_FILE" ]] && prev="$(cat "$STATE_FILE" 2>/dev/null || true)"
|
||||
|
||||
curr="$(current_addr)"
|
||||
|
||||
# Always update the state file so the next run sees a fresh baseline.
|
||||
printf '%s' "$curr" > "$STATE_FILE"
|
||||
|
||||
# No device present — nothing to do. Don't touch the service.
|
||||
if [[ -z "$curr" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
reason=""
|
||||
|
||||
if [[ -z "$prev" ]]; then
|
||||
# First observation (or state file was wiped). Only restart if the service
|
||||
# is also down — if it's already running, assume it's healthy and just
|
||||
# record the baseline.
|
||||
if ! service_active; then
|
||||
reason="device present at $curr but service is not active"
|
||||
fi
|
||||
elif [[ "$curr" != "$prev" ]]; then
|
||||
reason="device address changed: $prev → $curr (likely unplug/replug)"
|
||||
elif ! service_active; then
|
||||
reason="device present at $curr but service is not active"
|
||||
fi
|
||||
|
||||
if [[ -n "$reason" ]]; then
|
||||
echo "watchdog: $reason — restarting streamdeck-go"
|
||||
restart_service
|
||||
fi
|
||||
12
systemd/streamdeck-go-watchdog.timer
Normal file
12
systemd/streamdeck-go-watchdog.timer
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Stream Deck watchdog timer (every 30s)
|
||||
Documentation=https://git.i0t.app/WoodardDigital/streamdeck-go
|
||||
|
||||
[Timer]
|
||||
OnBootSec=30s
|
||||
OnUnitActiveSec=30s
|
||||
AccuracySec=5s
|
||||
Unit=streamdeck-go-watchdog.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Stream Deck controller
|
||||
Documentation=https://github.com/WoodardDigital/streamdeck-go
|
||||
Documentation=https://git.i0t.app/lwoodard/streamdeck-go
|
||||
After=graphical-session.target
|
||||
PartOf=graphical-session.target
|
||||
|
||||
|
||||
Reference in New Issue
Block a user