101 lines
2.9 KiB
Bash
Executable File
101 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Monitor agent - multiplexed serial monitor for AI interaction
|
|
# Usage: ./scripts/monitor-agent.sh <board>
|
|
#
|
|
# Outputs:
|
|
# - /tmp/doorbell-$BOARD.jsonl - JSON Lines log {"ts":123.456,"line":"..."}
|
|
# - /tmp/doorbell-$BOARD-state.json - Current device state
|
|
# - /tmp/doorbell-$BOARD-cmd.fifo - Command pipe (echo 'cmd' > fifo)
|
|
#
|
|
# Note: This script should be run after 'mise run kill' to ensure
|
|
# any existing processes using the serial port are terminated.
|
|
#
|
|
# Usage:
|
|
# mise run kill BOARD=$BOARD
|
|
# ./scripts/monitor-agent.sh $BOARD
|
|
# tail -f /tmp/doorbell-$BOARD.jsonl # Watch logs
|
|
# echo 'dashboard' > /tmp/doorbell-$BOARD-cmd.fifo # Send command
|
|
|
|
set -euo pipefail
|
|
|
|
BOARD="${1:-esp32-32e-4}"
|
|
source "./boards/$BOARD/board-config.sh"
|
|
|
|
SERIAL="$PORT"
|
|
LOGFILE="/tmp/doorbell-$BOARD.jsonl"
|
|
STATEFILE="/tmp/doorbell-$BOARD-state.json"
|
|
CMDFIFO="/tmp/doorbell-$BOARD-cmd.fifo"
|
|
SCREENSOCK="doorbell-$BOARD"
|
|
|
|
# Cleanup
|
|
cleanup() {
|
|
screen -S "$SCREENSOCK" -X quit 2>/dev/null || true
|
|
rm -f "$CMDFIFO"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Create command FIFO
|
|
rm -f "$CMDFIFO"
|
|
mkfifo "$CMDFIFO"
|
|
|
|
# Initialize state
|
|
echo '{"screen":"BOOT","deviceState":"BOOTED","backlightOn":false}' > "$STATEFILE"
|
|
|
|
# Start screen in detached mode with logging
|
|
# -L: enable logging
|
|
# -Logfile: specify log file
|
|
# -d -m: create detached
|
|
# -S: session name
|
|
screen -L -Logfile "$LOGFILE.raw" -d -m -S "$SCREENSOCK" "$SERIAL" 115200
|
|
|
|
# Give screen time to start
|
|
sleep 1
|
|
|
|
# Reader: parse raw screen log -> JSON Lines + state
|
|
(
|
|
exec >>"$LOGFILE" 2>&1
|
|
last_screen_line=""
|
|
while IFS= read -r line; do
|
|
# Skip duplicate/corrupted lines
|
|
[[ "$line" == "$last_screen_line" ]] && continue
|
|
last_screen_line="$line"
|
|
|
|
# Only process non-empty lines
|
|
[[ -z "$line" ]] && continue
|
|
|
|
TS=$(date +%s.%3N)
|
|
printf '{"ts":%s,"line":"%s"}\n' "$TS" "$line"
|
|
|
|
# Parse state changes
|
|
case "$line" in
|
|
*"[STATE]"*"→ OFF"*) echo '{"screen":"OFF"}' > "$STATEFILE" ;;
|
|
*"[STATE]"*"→ DASHBOARD"*) echo '{"screen":"DASHBOARD"}' > "$STATEFILE" ;;
|
|
*"[STATE]"*"→ ALERT"*) echo '{"screen":"ALERT"}' > "$STATEFILE" ;;
|
|
*"[STATE]"*"→ BOOT"*) echo '{"screen":"BOOT"}' > "$STATEFILE" ;;
|
|
*"[ADMIN]"*"dashboard"*) echo '{"screen":"DASHBOARD"}' > "$STATEFILE" ;;
|
|
*"[ADMIN]"*"off"*) echo '{"screen":"OFF"}' > "$STATEFILE" ;;
|
|
esac
|
|
done < "$LOGFILE.raw"
|
|
) &
|
|
READER_PID=$!
|
|
|
|
# Writer: command FIFO -> screen session
|
|
(
|
|
while IFS= read -r cmd < "$CMDFIFO"; do
|
|
# Send command to screen session
|
|
screen -S "$SCREENSOCK" -X stuff "$cmd^M"
|
|
echo "[SENT] $cmd"
|
|
done
|
|
) &
|
|
WRITER_PID=$!
|
|
|
|
echo "Monitor agent started (BOARD=$BOARD):"
|
|
echo " Log: $LOGFILE"
|
|
echo " State: $STATEFILE"
|
|
echo " Cmd: echo 'dashboard' > $CMDFIFO"
|
|
echo ""
|
|
echo "Press Ctrl+C to exit"
|
|
|
|
# Wait for reader
|
|
wait "$READER_PID" || true
|