db04341f7c
- Rewrite telemetry-synology.sh: canonical GL format (modem_0001/wan keys), self-contained metrics (no aiwanbal), Eyeride GPS with IP geo fallback - Add /api/fleet-telemetry to hub: joins tunnel status with fleet Postgres - Update dashboard.html: per-device WAN health bars, GPS, signal strength - Fix hub/ingest.sh normalisation: remap old wan1/wan2 → modem_0001/wan - Bump SPK version: 0.1-0001 → 0.5.0-0001 for GL parity Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
157 lines
5.3 KiB
Bash
157 lines
5.3 KiB
Bash
#!/bin/sh
|
|
# hub/ingest.sh — Fleet hub telemetry ingest + config backup receiver.
|
|
# Runs on the busfleet hub (167.172.237.162).
|
|
#
|
|
# Routes:
|
|
# POST /api/telemetry Receive telemetry JSON, normalise, store
|
|
# POST /api/backup Receive config backup archive
|
|
#
|
|
# Normalises both GL (openwrt) and Synology telemetry into a single schema.
|
|
|
|
set -e
|
|
|
|
HUB_DIR="${HUB_DIR:-/opt/busfleet-hub}"
|
|
TELEM_DIR="${TELEM_DIR:-${HUB_DIR}/telemetry}"
|
|
BACKUP_DIR="${BACKUP_DIR:-${HUB_DIR}/backups}"
|
|
|
|
mkdir -p "$TELEM_DIR" "$BACKUP_DIR"
|
|
|
|
# ── Normalise telemetry ────────────────────────────────────────────
|
|
# Both platforms POST to /api/telemetry.
|
|
# Canonical format uses modem_0001/wan keys (matching GL standard).
|
|
# Handles three variants:
|
|
# - GL (no platform field): add platform="openwrt", pass through
|
|
# - GL (platform="openwrt"): already canonical, pass through
|
|
# - Old Synology (platform="synology" + wan1/wan2): remap to modem_0001/wan
|
|
# - New unified Synology (platform="synology" + modem_0001/wan): pass through
|
|
normalise_telemetry() {
|
|
json="$1"
|
|
platform=""
|
|
|
|
platform=$(echo "$json" | grep -o '"platform":"[^"]*"' | cut -d'"' -f4)
|
|
if [ -z "$platform" ]; then
|
|
# Pre-unified GL telemetry — add platform field, keys already canonical
|
|
platform="openwrt"
|
|
json=$(echo "$json" | sed \
|
|
-e 's/^{/{"platform":"'"$platform"'",/')
|
|
fi
|
|
|
|
# Remap old Synology wan1/wan2 keys to canonical modem_0001/wan
|
|
if echo "$json" | grep -q '"wan1"'; then
|
|
json=$(echo "$json" | sed \
|
|
-e 's/"wan1"/"modem_0001"/g' \
|
|
-e 's/"wan2"/"wan"/g')
|
|
fi
|
|
|
|
echo "$json"
|
|
}
|
|
|
|
# ── Store telemetry ────────────────────────────────────────────────
|
|
store_telemetry() {
|
|
local device_id="$1"
|
|
local json="$2"
|
|
local ts="$3"
|
|
local date_dir="" today=""
|
|
|
|
today=$(date -d "@$ts" +%Y-%m-%d 2>/dev/null || date +%Y-%m-%d)
|
|
date_dir="${TELEM_DIR}/${device_id}/${today}"
|
|
mkdir -p "$date_dir"
|
|
|
|
# Store as individual JSON lines (one per POST) for easy querying
|
|
echo "$json" >> "${date_dir}/telemetry.jsonl"
|
|
|
|
# Also update latest for quick dashboard reads
|
|
echo "$json" > "${date_dir}/latest.json"
|
|
echo "$json" > "${TELEM_DIR}/${device_id}/latest.json"
|
|
}
|
|
|
|
# ── Store config backup ────────────────────────────────────────────
|
|
store_backup() {
|
|
local device_id="$1"
|
|
local platform="$2"
|
|
local timestamp="$3"
|
|
local tmpfile="$4"
|
|
|
|
local dir="${BACKUP_DIR}/${device_id}"
|
|
mkdir -p "$dir"
|
|
|
|
# Store the backup file
|
|
cp "$tmpfile" "${dir}/${timestamp}-${platform}.tar.gz"
|
|
|
|
# Keep last 10 backups per device, delete older ones
|
|
ls -t "${dir}"/*.tar.gz 2>/dev/null | tail -n +11 | xargs rm -f 2>/dev/null || true
|
|
|
|
# Log
|
|
echo "$(date -Iseconds) backup: ${device_id} ${platform} ${timestamp}" >> "${BACKUP_DIR}/backup.log"
|
|
}
|
|
|
|
# ── CGI/HTTP Handler (called by socat or netcat listener) ─────────
|
|
handle_request() {
|
|
local method="$1"
|
|
local path="$2"
|
|
local body="$3"
|
|
local content_type="$4"
|
|
|
|
case "$path" in
|
|
/api/telemetry)
|
|
# Expect JSON body
|
|
local device_id="" ts="" normalised=""
|
|
device_id=$(echo "$body" | grep -o '"device_id":"[^"]*"' | cut -d'"' -f4)
|
|
ts=$(echo "$body" | grep -o '"timestamp":[0-9]*' | grep -o '[0-9]*')
|
|
|
|
[ -z "$device_id" ] && { echo '{"error":"missing device_id"}'; return 1; }
|
|
|
|
normalised=$(normalise_telemetry "$body")
|
|
store_telemetry "$device_id" "$normalised" "${ts:-0}"
|
|
echo '{"status":"ok"}'
|
|
;;
|
|
|
|
/api/backup)
|
|
# Multipart form data — device_id, platform, timestamp, file
|
|
# For simplicity: socat passes raw body; caller uses curl -F
|
|
# The CGI wrapper extracts multipart parts
|
|
echo '{"status":"ok","note":"backup received"}'
|
|
;;
|
|
|
|
/api/status)
|
|
# Fleet status summary
|
|
echo '{"status":"ok","devices":[]}'
|
|
;;
|
|
|
|
*)
|
|
echo '{"error":"not found"}'
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ── CLI mode ──────────────────────────────────────────────────────
|
|
case "${1:-}" in
|
|
--ingest)
|
|
# Pipe JSON stdin → normalise → store
|
|
body=$(cat)
|
|
handle_request "POST" "/api/telemetry" "$body" "application/json"
|
|
;;
|
|
--backup)
|
|
device_id="$2"
|
|
platform="$3"
|
|
timestamp="$4"
|
|
file="$5"
|
|
store_backup "$device_id" "$platform" "$timestamp" "$file"
|
|
;;
|
|
--status)
|
|
echo "=== Fleet Hub Status ==="
|
|
echo "Telemetry dir: $TELEM_DIR"
|
|
echo "Backup dir: $BACKUP_DIR"
|
|
echo ""
|
|
echo "Devices reporting:"
|
|
ls "$TELEM_DIR" 2>/dev/null || echo " (none)"
|
|
echo ""
|
|
echo "Backups:"
|
|
find "$BACKUP_DIR" -name "*.tar.gz" 2>/dev/null | sort || echo " (none)"
|
|
;;
|
|
*)
|
|
echo "Usage: ingest.sh --ingest | --backup <id> <platform> <ts> <file> | --status"
|
|
;;
|
|
esac
|