Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:

- name: Install Python Dependencies & Security Tools
run: |
python -m pip install pip==24.0
python -m pip install --only-binary :all: pip==24.0
pip install --only-binary :all: bandit==1.8.3 safety==3.3.1 pytest==8.3.4 httpx==0.28.1 pytest-asyncio==0.25.3
if [ -f backend/requirements.txt ]; then pip install --only-binary :all: --require-hashes -r backend/requirements.txt; fi

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/iot-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

- name: Install PlatformIO CLI
run: |
python -m pip install pip==24.0
python -m pip install --only-binary :all: pip==24.0
pip install --only-binary :all: platformio==6.1.19

- name: Inject CI Environment Variables
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
run: cp android/app/build/outputs/apk/release/app-release.apk ./QuakeGuard.apk

- name: Upload APK as Workflow Artifact (For PRs/Testing)
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: QuakeGuard-APK
path: mobile/QuakeGuard.apk
Expand Down
13 changes: 10 additions & 3 deletions docs/web/quakeguard.html
Original file line number Diff line number Diff line change
Expand Up @@ -937,12 +937,19 @@ <h2 class="qg-title" data-i18n="exp_title">The experience</h2>
<p class="qg-lead" data-i18n="exp_note" style="max-width:720px;margin:0 auto;">Watch the demo with
captions available in English and Italian.</p>
</div>
<div class="row">
<div class="col-lg-10 mx-auto">
<div class="ratio ratio-16x9" style="max-width:800px; margin:0 auto; background:#000; border-radius:16px; overflow:hidden; border:1px solid rgba(255,255,255,0.12);">
<div class="row g-4">
<div class="col-lg-6">
<h4 class="text-center mb-3 text-white fw-semibold" data-i18n="exp_trailer_title">Trailer</h4>
<div class="ratio ratio-16x9" style="background:#000; border-radius:16px; overflow:hidden; border:1px solid rgba(255,255,255,0.12);">
<iframe src="https://www.youtube.com/embed/Nwnah5GTkrk" title="QuakeGuard Demo" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="border:0;"></iframe>
</div>
</div>
<div class="col-lg-6">
<h4 class="text-center mb-3 text-white fw-semibold" data-i18n="exp_explanation_title">Explanation</h4>
<div class="ratio ratio-16x9" style="background:#000; border-radius:16px; overflow:hidden; border:1px solid rgba(255,255,255,0.12);">
<iframe src="https://www.youtube.com/embed/whOCWCu1Xxg" title="QuakeGuard Explanation" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="border:0;"></iframe>
</div>
</div>
</div>
</div>
</section>
Expand Down
2 changes: 2 additions & 0 deletions docs/web/quakeguard.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pr_body.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This PR finalizes the `v2.1.1` release for QuakeGuard. It corrects critical bugs
* **`docs/whitepaper/16-appendix.typ` & `QuakeGuard_Technical_Report_v2.1.1.pdf`**: Rewrote Appendix A to fully document the cascade effect of the demo endpoint (DB inserts, AI Worker trigger, fake telemetry generation). Re-compiled the Typst whitepaper.
* **Repository-wide Version Bump**: Systematically updated all versions from `2.1.0` to `2.1.1` across `package.json`, `.cff`, `.js`, `settings.tsx`, OpenAPI docs, SVGs, and `CHANGELOG.md`. Also removed a ghost "Timeseries" roadmap item that was already completed in v1.2.1.
* **`backend/tests/unit/test_schemas.py`**: Fixed a failing unit test asserting the old `7.5` magnitude default. All 157 tests now pass.
* **`scripts/hollywood.py`**: Refactored sensor generation by introducing a `SENSORS_PER_CITY` constant, removed legacy variables, and cleaned up unused comments.
* **`scripts/quakeguard_init.sh`**: Replaced the multi-window `ptyxis` startup with a unified `tmux` dashboard grid for better UX, consolidating Backend, Mobile, and IoT panes into a single terminal window with mouse support.

## Impact & Next Steps
This ensures the QuakeGuard demo functionality is statistically robust, spatially accurate, and safely bounded for public exhibitions. It also guarantees a completely clean `v2.1.1` release with no mismatched tags or documentation ghosts.
Expand Down
6 changes: 3 additions & 3 deletions scripts/hollywood.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
MQTT_USERNAME = os.getenv("MQTT_USERNAME", None)
MQTT_PASSWORD = os.getenv("MQTT_PASSWORD", None)

NUM_SENSORS = 50
SENSORS_PER_CITY = 7
FLEET_FILE = os.path.join(os.path.dirname(__file__), "fleet.json")

CITIES = {
Expand Down Expand Up @@ -193,7 +193,7 @@ async def _register_fleet():
sensors = []
print("🏭 Generating new global fleet...")
for city_name in CITIES.keys():
for _ in range(7):
for _ in range(SENSORS_PER_CITY):
base_lat, base_lon = CITIES[city_name]
lat = base_lat + (-0.1 + secrets.SystemRandom().random() * (0.1 - -0.1)) # NOSONAR - geographic jitter, not cryptographic
lon = base_lon + (-0.1 + secrets.SystemRandom().random() * (0.1 - -0.1)) # NOSONAR - geographic jitter, not cryptographic
Expand Down Expand Up @@ -265,4 +265,4 @@ async def main():
print(f"❌ MQTT Connection Error: {e}")

if __name__ == "__main__":
asyncio.run(main())
asyncio.run(main())
191 changes: 123 additions & 68 deletions scripts/quakeguard_init.sh
Original file line number Diff line number Diff line change
@@ -1,66 +1,149 @@
#!/bin/bash

# ==============================================================================
# CONSOLE MODE: Executed ONLY in the Top-Right pane
# ==============================================================================
if [[ "$1" == "--console" ]]; then
SESSION="quakeguard-cc"
PROJECT_ROOT="$2"

# Function to print the QR Code
print_qr() {
if [[ -f /tmp/qg_tunnel_output.log ]]; then
cat /tmp/qg_tunnel_output.log
echo "---------------------------------------------------------"
else
echo "❌ No QR Code found in /tmp/qg_tunnel_output.log"
fi
return 0
}

# Function to print the Menu
print_menu() {
echo "✅ QuakeGuard Command Center Active!"
echo "🔗 Quick Links:"
echo " - 📚 Swagger API: http://localhost:8000/docs"
echo " - 📊 Grafana: http://localhost:3000"
echo ""
echo "🎛️ Available commands:"
echo " 'backend' -> Restart Docker (Top-Left)"
echo " 'mobile' -> Restart Expo (Bottom-Left)"
echo " 'iot' -> Restart ESP32 (Bottom-Right)"
echo " 'hollywood' -> Launch/Restart Hollywood (Hidden Tab #1)"
echo " 'qr' -> Show Cloudflare tunnel QR Code"
echo " 'help/menu' -> Show this command list"
echo " 'exit' -> Close everything and exit"
echo ""
return 0
}

clear
print_qr
print_menu

while true; do
read -p "QuakeGuard> " cmd
case "$cmd" in
backend)
tmux send-keys -t $SESSION:0.0 C-c
tmux send-keys -t $SESSION:0.0 "docker compose --profile ai up --build" C-m
echo "🚀 Backend restarted."
;;
mobile)
tmux send-keys -t $SESSION:0.1 C-c
tmux send-keys -t $SESSION:0.1 "npx expo start --clear" C-m
echo "🚀 Mobile (Expo) restarted."
;;
iot)
tmux send-keys -t $SESSION:0.3 C-c
tmux send-keys -t $SESSION:0.3 "pio run -t upload -t monitor" C-m
echo "🚀 Firmware restarted."
;;
hollywood)
tmux kill-window -t $SESSION:1 2>/dev/null
tmux new-window -t $SESSION -n "Hollywood" "cd '$PROJECT_ROOT' && ./scripts/hollywood.sh"
tmux select-window -t $SESSION:0
echo "🚀 Hollywood Simulator launched! (Press Ctrl+B, then 1 to view. Ctrl+B, then 0 to return)."
;;
qr)
clear
print_qr
;;
help|menu)
print_menu
;;
exit|quit)
echo "👋 Closing Command Center..."
tmux kill-session -t $SESSION 2>/dev/null
break
;;
*)
if [[ -n "$cmd" ]]; then
echo "❌ Unknown command. Type 'help' or 'menu' for the command list."
fi
;;
esac
done
exit 0
fi

# ==============================================================================
# STANDARD MODE: Environment setup and Tmux grid generation
# ==============================================================================

echo "🚀 Initializing QuakeGuard Command Center..."

# Get absolute paths dynamically based on script location
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

# Auto-generate secrets on first boot
if [[ ! -f "$PROJECT_ROOT/backend/.env" ]]; then
echo "⚠️ First boot detected: backend/.env not found."
echo "🔐 Running secret generator to provision fresh .env files..."
echo "🔐 Running secret generator..."
"$SCRIPT_DIR/generate_secrets.sh"
echo ""
fi

# Capture the tunnel output (including QR) into the temporary file
echo "🌐 Running tunnel automation..."
"$SCRIPT_DIR/tunnel_init.sh"
if [[ $? -ne 0 ]]; then
"$SCRIPT_DIR/tunnel_init.sh" | tee /tmp/qg_tunnel_output.log
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
echo "❌ Tunnel script failed. Aborting."
exit 1
fi
echo ""

echo "🖥️ Opening 3 separate terminal windows (Ptyxis)..."
echo "🖥️ Transforming current terminal into the Tmux dashboard..."

# 1. Backend Window
ptyxis --new-window -d "$PROJECT_ROOT/backend" -T "Backend (Docker)" -- bash -c "echo '=== BACKEND (Docker) ==='; docker compose --profile ai up --build; exec bash" &
SESSION="quakeguard-cc"
tmux kill-session -t $SESSION 2>/dev/null

# 2. Mobile Window
# Adding a small delay so windows don't overlap completely at spawn
sleep 0.5
ptyxis --new-window -d "$PROJECT_ROOT/mobile" -T "Mobile (Expo)" -- bash -c "echo '=== MOBILE (Expo) ==='; npx expo start --clear; exec bash" &
# 1. Pane 0: Backend (Top-Left)
tmux new-session -d -s $SESSION -c "$PROJECT_ROOT/backend"
tmux send-keys -t $SESSION:0.0 "echo '=== BACKEND (Docker) ===' && docker compose --profile ai up --build" C-m

# 3. Firmware Window (Wait 30s for the Backend to be fully ready)
sleep 0.5
ptyxis --new-window -d "$PROJECT_ROOT/firmware" -T "IoT (ESP32)" -- bash -c "echo '=== IoT (ESP32) ==='; echo '⏳ Waiting 30 seconds for the backend to start...'; sleep 30; echo '🚀 Flashing new firmware with updated Cloudflare URL...'; pio run -t upload -t monitor; exec bash" &
# 📌 ENABLE MOUSE SUPPORT IN TMUX (For scrolling and pane selection)
tmux set-option -g mouse on

echo ""
read -p "🎬 Do you want to start the Hollywood Simulator for Grafana? [y/N]: " run_hollywood
if [[ "$run_hollywood" =~ ^[Yy]$ ]]; then
echo "🎥 Hollywood Simulator will launch in a new terminal..."
sleep 0.5
ptyxis --new-window -d "$PROJECT_ROOT" -T "Hollywood (Demo)" -- bash -c "echo '=== HOLLYWOOD SIMULATOR ==='; echo '⏳ Waiting 20 seconds for the backend to start...'; sleep 20; ./scripts/hollywood.sh; exec bash" &
fi
# Split in half (Creates the Right side)
tmux split-window -h -t $SESSION -c "$PROJECT_ROOT"

echo ""
echo "✅ All terminals launched successfully!"
echo ""
echo "🔗 QuakeGuard Command Center Links:"
echo " - 📚 Swagger API Docs: http://localhost:8000/docs"
echo " - 📊 Grafana Dashboard: http://localhost:3000"
echo ""
echo "🎛️ Command Center Console is active."
echo "Type a command to restart a component if a terminal was accidentally closed:"
echo " 'backend' -> Relaunch Backend (Docker)"
echo " 'mobile' -> Relaunch Mobile (Expo)"
echo " 'iot' -> Relaunch Firmware (ESP32)"
echo " 'hollywood' -> Relaunch Hollywood Simulator"
echo " 'exit' -> Close this Command Center"
echo ""
# 2. Split the Left half in two -> Pane 1: Mobile (Bottom-Left)
tmux select-pane -t $SESSION:0.0
tmux split-window -v -t $SESSION:0.0 -c "$PROJECT_ROOT/mobile"
tmux send-keys -t $SESSION:0.1 "echo '=== MOBILE (Expo) ===' && npx expo start --clear" C-m

# 3. Split the Right half in two -> Pane 3: IoT (Bottom-Right)
tmux select-pane -t $SESSION:0.2
tmux split-window -v -t $SESSION:0.2 -c "$PROJECT_ROOT/firmware"
tmux send-keys -t $SESSION:0.3 "echo '=== IoT (ESP32) ===' && echo '⏳ Waiting 30s...' && sleep 30 && pio run -t upload -t monitor" C-m

# 4. Pane 2 (Top-Right): Start the interactive Console
tmux send-keys -t $SESSION:0.2 "\"$BASH_SOURCE\" --console \"$PROJECT_ROOT\"" C-m

# Set final focus on the Console (Top-Right)
tmux select-pane -t $SESSION:0.2

# Background job to wait for Grafana and open it (silenced output to not mess up the prompt)
# Background job to open Grafana
(
for i in {1..30}; do
if curl -s http://localhost:3000/login > /dev/null; then
Expand All @@ -75,33 +158,5 @@ echo ""
done
) &

while true; do
read -p "QuakeGuard> " cmd
case "$cmd" in
backend)
ptyxis --new-window -d "$PROJECT_ROOT/backend" -T "Backend (Docker)" -- bash -c "echo '=== BACKEND (Docker) ==='; docker compose --profile ai up --build; exec bash" &
echo "🚀 Relaunched Backend window."
;;
mobile)
ptyxis --new-window -d "$PROJECT_ROOT/mobile" -T "Mobile (Expo)" -- bash -c "echo '=== MOBILE (Expo) ==='; npx expo start --clear; exec bash" &
echo "🚀 Relaunched Mobile window."
;;
iot)
ptyxis --new-window -d "$PROJECT_ROOT/firmware" -T "IoT (ESP32)" -- bash -c "echo '=== IoT (ESP32) ==='; pio run -t upload -t monitor; exec bash" &
echo "🚀 Relaunched Firmware window."
;;
hollywood)
ptyxis --new-window -d "$PROJECT_ROOT" -T "Hollywood (Demo)" -- bash -c "echo '=== HOLLYWOOD SIMULATOR ==='; ./scripts/hollywood.sh; exec bash" &
echo "🚀 Relaunched Hollywood Simulator window."
;;
exit|quit)
echo "👋 Closing Command Center. Goodbye!"
break
;;
*)
if [[ -n "$cmd" ]]; then
echo "❌ Unknown command. Available: backend, mobile, iot, hollywood, exit"
fi
;;
esac
done
# Attach the terminal to the Tmux session
exec tmux attach-session -t $SESSION
Loading