-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhost_auto_startup_launcher.sh
More file actions
executable file
·220 lines (184 loc) · 7.01 KB
/
host_auto_startup_launcher.sh
File metadata and controls
executable file
·220 lines (184 loc) · 7.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/usr/bin/env bash
set -Eeuo pipefail
###############################################################################
# Flo Simon Says – host-side auto-startup helper
# → waits for Wi-Fi, then pulls code & fires up docker-compose
###############################################################################
# Log everything for post-mortem debugging
LOGFILE="$HOME/flo_game_startup.log"
exec &> >(tee -a "$LOGFILE")
notify_desktop() {
local urgency="$1"
local title="$2"
local message="$3"
if ! command -v notify-send >/dev/null 2>&1; then
return 0
fi
DBUS_SESSION_BUS_ADDRESS="${DBUS_SESSION_BUS_ADDRESS:-unix:path=/run/user/$(id -u)/bus}" \
notify-send -u "$urgency" "$title" "$message" || true
}
confirm_startup() {
local title="Game Demo Startup"
local message="Do you want to bring up the game demo system now? Make sure you have wifi connection before starting."
if command -v zenity >/dev/null 2>&1; then
DBUS_SESSION_BUS_ADDRESS="${DBUS_SESSION_BUS_ADDRESS:-unix:path=/run/user/$(id -u)/bus}" \
zenity --question \
--title="$title" \
--text="$message" \
--ok-label="Start" \
--cancel-label="Not now"
return $?
fi
if command -v kdialog >/dev/null 2>&1; then
kdialog --title "$title" --yesno "$message" --yes-label "Start" --no-label "Not now"
return $?
fi
if command -v xmessage >/dev/null 2>&1; then
xmessage -center -buttons "Start:0,Not now:1" "$message"
return $?
fi
echo "$(date '+%F %T') [WARN] No GUI dialog tool found (zenity/kdialog/xmessage)."
notify_desktop normal "$title" \
"No dialog tool found, so auto startup will continue immediately."
return 0
}
wait_for_gui_session() {
local attempts="${1:-60}"
local sleep_seconds="${2:-2}"
export DISPLAY="${DISPLAY:-:0}"
export XAUTHORITY="${XAUTHORITY:-$HOME/.Xauthority}"
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
export DBUS_SESSION_BUS_ADDRESS="${DBUS_SESSION_BUS_ADDRESS:-unix:path=${XDG_RUNTIME_DIR}/bus}"
for ((i = 1; i <= attempts; i++)); do
if [ -S "${XDG_RUNTIME_DIR}/bus" ] \
&& [ -e "$XAUTHORITY" ] \
&& command -v xdpyinfo >/dev/null 2>&1 \
&& xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then
echo "$(date '+%F %T') [INFO] GUI session is ready on ${DISPLAY}"
return 0
fi
echo "$(date '+%F %T') [WARN] Waiting for graphical session (${i}/${attempts})"
sleep "$sleep_seconds"
done
echo "$(date '+%F %T') [WARN] Graphical session did not become ready in time."
return 1
}
announce_step() {
local message="$1"
echo "$(date '+%F %T') [INFO] ${message}"
notify_desktop normal "Auto bring up robot" "$message"
}
fail_with_notification() {
local message="$1"
echo "$(date '+%F %T') [ERROR] ${message}"
notify_desktop critical "Auto bring up robot failed" "$message"
exit 1
}
on_error() {
local exit_code="$1"
local line_no="$2"
notify_desktop critical "Auto bring up robot failed" \
"Startup stopped near line ${line_no}. Check ${LOGFILE} for details."
exit "$exit_code"
}
trap 'on_error $? $LINENO' ERR
run_privileged() {
if [ "$(id -u)" -eq 0 ]; then
"$@"
else
sudo -n "$@"
fi
}
wait_for_path() {
local label="$1"
local path="$2"
local attempts="${3:-30}"
local sleep_seconds="${4:-1}"
for ((i = 1; i <= attempts; i++)); do
if [ -e "$path" ]; then
echo "$(date '+%F %T') [INFO] ${label} available at ${path}"
return 0
fi
echo "$(date '+%F %T') [WARN] Waiting for ${label} at ${path} (${i}/${attempts})"
sleep "$sleep_seconds"
done
echo "$(date '+%F %T') [ERROR] ${label} missing at ${path}"
return 1
}
###############################################################################
# Wait for Wi-Fi connectivity
###############################################################################
MAX_WAIT=90 # seconds before we give up
CHECK_INTERVAL=3 # seconds between checks
ELAPSED=0
announce_step "Waiting for graphical session"
if ! wait_for_gui_session 90 2; then
fail_with_notification "Desktop session was not ready, so the startup confirmation dialog could not be shown."
fi
if ! confirm_startup; then
announce_step "Startup canceled by user"
exit 0
fi
announce_step "Auto bring up robot"
announce_step "Waiting for Wi-Fi connectivity"
while ! ping -q -c1 -W1 8.8.8.8 &>/dev/null; do
sleep "$CHECK_INTERVAL"
ELAPSED=$((ELAPSED + CHECK_INTERVAL))
if (( ELAPSED >= MAX_WAIT )); then
fail_with_notification "No Internet after ${MAX_WAIT}s. Please check Wi-Fi."
fi
done
announce_step "Wi-Fi is online"
###############################################################################
# Git repo settings (unchanged)
###############################################################################
REPO_URL="https://github.com/anht-nguyen/FloSystemV2_GameDemo.git"
CLONE_DIR="$HOME/FloSystemV2_GameDemo"
# Clone or update the repo
if [ ! -d "$CLONE_DIR/.git" ]; then
announce_step "Cloning robot software"
git clone --branch master "$REPO_URL" "$CLONE_DIR" || {
fail_with_notification "Git clone failed. Check network and repository access."
}
else
announce_step "Updating robot software"
cd "$CLONE_DIR" || exit 1
git fetch origin master && git reset --hard origin/master || {
fail_with_notification "Git update failed. Check network and repository access."
}
fi
###############################################################################
# Launch container (unchanged logic)
###############################################################################
cd "$CLONE_DIR" || {
fail_with_notification "Could not open the project directory."
}
announce_step "Checking robot USB devices"
if ! wait_for_path "camera symlink" /dev/flo_camera 30 1 \
|| ! wait_for_path "motors symlink" /dev/flo_motors 30 1 \
|| ! wait_for_path "face symlink" /dev/flo_face 30 1; then
echo "$(date '+%F %T') [WARN] FLO symlinks did not appear after waiting."
echo "$(date '+%F %T') [WARN] Attempting a udev retrigger."
notify_desktop normal "Auto bring up robot" \
"Devices not found yet. Retrying udev and checking USB devices again."
if run_privileged udevadm control --reload-rules && run_privileged udevadm trigger; then
wait_for_path "camera symlink" /dev/flo_camera 15 1
wait_for_path "motors symlink" /dev/flo_motors 15 1
wait_for_path "face symlink" /dev/flo_face 15 1
else
fail_with_notification "Devices not found. Please check the USB cables and plug in the robot USB devices."
fi
fi
announce_step "Robot devices detected"
announce_step "Starting robot Docker container"
# Ensure current user is in docker group
if ! id -nG "$USER" | grep -qw docker; then
echo "[WARN] User '$USER' not in 'docker' group; this may require sudo rights."
notify_desktop normal "Auto bring up robot" \
"User '$USER' is not in the docker group. Startup may require sudo rights."
fi
# Build and run in detached mode
"$CLONE_DIR/docker_compose_up.sh" || {
fail_with_notification "Failed to start the robot container. Check ${LOGFILE} for details."
}
announce_step "Robot container launched successfully"