feat: remote commands, systemd units, process observability, broker auth split
- Command intake (reboot/shutdown) on infoscreen/{uuid}/commands with ack lifecycle
- MQTT_USER/MQTT_PASSWORD_BROKER split from identity vars; configure_mqtt_security() updated
- infoscreen-simclient.service: Type=notify, WatchdogSec=60, Restart=on-failure
- infoscreen-notify-failure@.service + script: retained MQTT alert when systemd gives up (Gap 3)
- _sd_notify() watchdog keepalive in simclient main loop (Gap 1)
- broker_connection block in health payload: reconnect_count, last_disconnect_at (Gap 2)
- COMMAND_MOCK_REBOOT_IMMEDIATE_COMPLETE canary flag with safety guard
- SERVER_TEAM_ACTIONS.md: server-side integration action items
- Docs: README, CHANGELOG, src/README, copilot-instructions updated
- 43 tests passing
This commit is contained in:
55
scripts/infoscreen-notify-failure.sh
Executable file
55
scripts/infoscreen-notify-failure.sh
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env bash
|
||||
# Publishes a service-failed MQTT notification when called by systemd OnFailure=.
|
||||
# Usage: infoscreen-notify-failure.sh <failing-unit-name>
|
||||
#
|
||||
# Designed to be called from infoscreen-notify-failure@.service.
|
||||
# Reads broker credentials from .env; reads client UUID from config.
|
||||
# Safe to run even if MQTT is unreachable (exits cleanly, errors logged to journal).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
FAILING_UNIT="${1:-unknown}"
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENV_FILE="$PROJECT_DIR/.env"
|
||||
UUID_FILE="$PROJECT_DIR/src/config/client_uuid.txt"
|
||||
|
||||
# Load .env (skip comments and blank lines)
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source <(grep -v '^\s*#' "$ENV_FILE" | grep -v '^\s*$')
|
||||
set +a
|
||||
fi
|
||||
|
||||
MQTT_BROKER="${MQTT_BROKER:-localhost}"
|
||||
MQTT_PORT="${MQTT_PORT:-1883}"
|
||||
MQTT_USER="${MQTT_USER:-}"
|
||||
MQTT_PASSWORD_BROKER="${MQTT_PASSWORD_BROKER:-}"
|
||||
|
||||
CLIENT_UUID="unknown"
|
||||
if [[ -f "$UUID_FILE" ]]; then
|
||||
CLIENT_UUID="$(cat "$UUID_FILE" | tr -d '[:space:]')"
|
||||
fi
|
||||
|
||||
TOPIC="infoscreen/${CLIENT_UUID}/service_failed"
|
||||
TIMESTAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
|
||||
PAYLOAD=$(printf '{"event":"service_failed","unit":"%s","client_uuid":"%s","failed_at":"%s"}' \
|
||||
"$FAILING_UNIT" "$CLIENT_UUID" "$TIMESTAMP")
|
||||
|
||||
# Build mosquitto_pub auth args
|
||||
AUTH_ARGS=()
|
||||
if [[ -n "$MQTT_USER" ]]; then AUTH_ARGS+=(-u "$MQTT_USER"); fi
|
||||
if [[ -n "$MQTT_PASSWORD_BROKER" ]]; then AUTH_ARGS+=(-P "$MQTT_PASSWORD_BROKER"); fi
|
||||
|
||||
echo "Publishing service-failed notification: unit=$FAILING_UNIT client=$CLIENT_UUID"
|
||||
|
||||
mosquitto_pub \
|
||||
-h "$MQTT_BROKER" \
|
||||
-p "$MQTT_PORT" \
|
||||
"${AUTH_ARGS[@]}" \
|
||||
-t "$TOPIC" \
|
||||
-m "$PAYLOAD" \
|
||||
-q 1 \
|
||||
--retain \
|
||||
2>&1 || echo "WARNING: mosquitto_pub failed (broker unreachable?); notification not delivered"
|
||||
Reference in New Issue
Block a user