-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRunVisionSystem.sh
More file actions
executable file
·177 lines (155 loc) · 5.27 KB
/
RunVisionSystem.sh
File metadata and controls
executable file
·177 lines (155 loc) · 5.27 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
#!/usr/bin/env bash
set -euo pipefail
# Always run from this repo’s root (where this script lives)
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
echo ">>> Vision System Starting"
# -----------------------------------------------------------------------------
# Hard "single instance" lock: do not allow this script to be run twice.
# -----------------------------------------------------------------------------
LOCK_FILE="$SCRIPT_DIR/.visionsystem.lock"
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
echo "ERROR: Vision System is already running (lock held: $LOCK_FILE)." >&2
echo " Stop the running instance before starting another." >&2
exit 1
fi
# -----------------------------------------------------------------------------
# Ensure venv exists and is usable
# -----------------------------------------------------------------------------
if [[ ! -d .venv ]]; then
python3 -m venv .venv
fi
# Make sure venv isn’t root-owned (common cause of pip perms errors)
if [[ ! -w ".venv/lib" ]]; then
if command -v sudo >/dev/null 2>&1; then
echo ">>> Fixing venv ownership (sudo)…"
sudo chown -R "$USER":"$USER" .venv
else
echo "ERROR: .venv not writable and no sudo available" >&2
exit 1
fi
fi
# Activate venv
# shellcheck disable=SC1091
source .venv/bin/activate
# Safety: avoid accidental global pip installs
export PIP_REQUIRE_VIRTUALENV=1
# Make sure pip itself is OK (pin below 25 to be conservative)
python - <<'PY' || true
import sys, subprocess
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "--upgrade", "pip<25", "setuptools", "wheel"], check=True)
PY
# Keep NumPy <2 to match your OpenCV build ABI
NUMPY_VER="$(python - <<'PY'
try:
import importlib.metadata as md
print(md.version("numpy"))
except Exception:
print("")
PY
)"
if [[ -z "${NUMPY_VER}" || "${NUMPY_VER%%.*}" -ge 2 ]]; then
echo ">>> Installing NumPy <2 for OpenCV compatibility…"
pip install -q --upgrade 'numpy<2'
fi
# Quick sanity check that OpenCV can import with this NumPy
python - <<'PY'
import numpy as np
import cv2
print(f">>> OpenCV {cv2.__version__} with NumPy {np.__version__} OK")
PY
# -----------------------------------------------------------------------------
# Firebase listener (REQUIRED)
# -----------------------------------------------------------------------------
LISTENER="$SCRIPT_DIR/components/machinelearning/listen.mjs"
if [[ ! -f "$LISTENER" ]]; then
echo "ERROR: Firebase listener not found at: $LISTENER" >&2
exit 1
fi
# Environment
export QT_QPA_PLATFORM=offscreen
export OPENCV_LOG_LEVEL=ERROR
export GST_DEBUG=0
# Resolve Node executable:
# 1) Prefer the explicit NVM-managed path used historically
# 2) Else try to load nvm + nvm use 18
# 3) Else fall back to node on PATH
NODE_EXE=""
PREFERRED_NODE="$HOME/.nvm/versions/node/v18.20.4/bin/node"
if [[ -x "$PREFERRED_NODE" ]]; then
NODE_EXE="$PREFERRED_NODE"
else
if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
# shellcheck disable=SC1090
. "$HOME/.nvm/nvm.sh"
nvm use 18 >/dev/null 2>&1 || true
fi
if command -v node >/dev/null 2>&1; then
NODE_EXE="$(command -v node)"
fi
fi
if [[ -z "$NODE_EXE" ]]; then
echo "ERROR: Node.js not found. Required to run $LISTENER" >&2
echo "Tried:" >&2
echo " - $PREFERRED_NODE" >&2
echo " - nvm use 18 (via \$HOME/.nvm/nvm.sh)" >&2
echo " - node on PATH" >&2
exit 1
fi
# -----------------------------------------------------------------------------
# Start both processes and supervise:
# - If listen.mjs exits -> terminate Python and exit non-zero
# - If Python exits -> terminate listener and exit with Python status
# - Ctrl-C / TERM kills both
# -----------------------------------------------------------------------------
NODE_PID=""
PY_PID=""
cleanup() {
set +e
if [[ -n "${PY_PID}" ]] && kill -0 "${PY_PID}" >/dev/null 2>&1; then
kill "${PY_PID}" >/dev/null 2>&1
wait "${PY_PID}" >/dev/null 2>&1
fi
if [[ -n "${NODE_PID}" ]] && kill -0 "${NODE_PID}" >/dev/null 2>&1; then
kill "${NODE_PID}" >/dev/null 2>&1
wait "${NODE_PID}" >/dev/null 2>&1
fi
}
trap cleanup INT TERM EXIT
echo ">>> Starting Firebase listener (required)..."
"$NODE_EXE" "$LISTENER" >/dev/null 2>&1 &
NODE_PID=$!
# Fail fast if listener dies immediately (syntax error, missing deps, auth crash, etc.)
sleep 1
if ! kill -0 "$NODE_PID" >/dev/null 2>&1; then
echo "ERROR: Firebase listener (listen.mjs) failed to start or exited immediately." >&2
echo " (Output is currently silenced; remove redirection to debug.)" >&2
exit 1
fi
echo ">>> Firebase listener running (pid $NODE_PID)"
echo ">>> Starting Python vision system..."
python main.py "$@" &
PY_PID=$!
echo ">>> Python running (pid $PY_PID)"
while true; do
if ! kill -0 "$NODE_PID" >/dev/null 2>&1; then
echo "ERROR: Firebase listener exited. Shutting down Vision System." >&2
if kill -0 "$PY_PID" >/dev/null 2>&1; then
kill "$PY_PID" >/dev/null 2>&1
fi
wait "$PY_PID" >/dev/null 2>&1 || true
exit 1
fi
if ! kill -0 "$PY_PID" >/dev/null 2>&1; then
wait "$PY_PID"
PY_STATUS=$?
echo ">>> Python exited (status $PY_STATUS). Stopping Firebase listener."
if kill -0 "$NODE_PID" >/dev/null 2>&1; then
kill "$NODE_PID" >/dev/null 2>&1
wait "$NODE_PID" >/dev/null 2>&1 || true
fi
exit "$PY_STATUS"
fi
sleep 0.5
done