v1.4.0 — Mise à jour firmware hors-ligne par upload ZIP
Nouvelle fonctionnalité permettant de mettre à jour le firmware sans connexion internet, via upload d'un fichier .zip depuis l'interface admin. Fichiers ajoutés: - update_firmware_from_file.sh (rsync + exclusions + chown + restart services) - .update-exclude (liste d'exclusions évolutive, versionnée) - html/.htaccess (limite upload PHP 50MB) Fichiers modifiés: - html/launcher.php (handler upload_firmware) - html/admin.html (UI upload + barre de progression) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
185
update_firmware_from_file.sh
Normal file
185
update_firmware_from_file.sh
Normal file
@@ -0,0 +1,185 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NebuleAir Pro 4G - Update from uploaded ZIP file
|
||||
# Usage: sudo ./update_firmware_from_file.sh /path/to/extracted/folder
|
||||
|
||||
echo "======================================"
|
||||
echo "NebuleAir Pro 4G - Firmware Update (File Upload)"
|
||||
echo "======================================"
|
||||
echo "Started at: $(date)"
|
||||
echo ""
|
||||
|
||||
# Set target directory
|
||||
TARGET_DIR="/var/www/nebuleair_pro_4g"
|
||||
EXCLUDE_FILE="$TARGET_DIR/.update-exclude"
|
||||
|
||||
# Function to print status messages
|
||||
print_status() {
|
||||
echo "[$(date '+%H:%M:%S')] $1"
|
||||
}
|
||||
|
||||
# Function to check command success
|
||||
check_status() {
|
||||
if [ $? -eq 0 ]; then
|
||||
print_status "✓ $1 completed successfully"
|
||||
else
|
||||
print_status "✗ $1 failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Validate arguments
|
||||
if [ -z "$1" ]; then
|
||||
print_status "✗ Error: No source directory provided"
|
||||
print_status "Usage: $0 /path/to/extracted/folder"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE_DIR="$1"
|
||||
|
||||
if [ ! -d "$SOURCE_DIR" ]; then
|
||||
print_status "✗ Error: Source directory does not exist: $SOURCE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 1: Validate source and compare versions
|
||||
print_status "Step 1: Validating update package..."
|
||||
|
||||
if [ ! -f "$SOURCE_DIR/VERSION" ]; then
|
||||
print_status "✗ Error: VERSION file not found in update package"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEW_VERSION=$(cat "$SOURCE_DIR/VERSION" | tr -d '[:space:]')
|
||||
OLD_VERSION="unknown"
|
||||
if [ -f "$TARGET_DIR/VERSION" ]; then
|
||||
OLD_VERSION=$(cat "$TARGET_DIR/VERSION" | tr -d '[:space:]')
|
||||
fi
|
||||
|
||||
print_status "Current version: $OLD_VERSION"
|
||||
print_status "New version: $NEW_VERSION"
|
||||
|
||||
# Step 2: Rsync with exclusions from .update-exclude
|
||||
print_status ""
|
||||
print_status "Step 2: Syncing files..."
|
||||
|
||||
# Build exclude args: use .update-exclude from the SOURCE (new version) if available,
|
||||
# otherwise fall back to the one already installed
|
||||
if [ -f "$SOURCE_DIR/.update-exclude" ]; then
|
||||
EXCLUDE_FILE="$SOURCE_DIR/.update-exclude"
|
||||
print_status "Using .update-exclude from update package"
|
||||
elif [ -f "$TARGET_DIR/.update-exclude" ]; then
|
||||
EXCLUDE_FILE="$TARGET_DIR/.update-exclude"
|
||||
print_status "Using .update-exclude from current installation"
|
||||
else
|
||||
print_status "⚠ No .update-exclude file found, using built-in defaults"
|
||||
# Fallback minimal exclusions
|
||||
EXCLUDE_FILE=$(mktemp)
|
||||
cat > "$EXCLUDE_FILE" <<'EXCL'
|
||||
sqlite/sensors.db
|
||||
sqlite/*.db-journal
|
||||
sqlite/*.db-wal
|
||||
logs/
|
||||
.git/
|
||||
config.json
|
||||
deviceID.txt
|
||||
wifi_list.csv
|
||||
envea/data/
|
||||
NPM/data/
|
||||
*.lock
|
||||
EXCL
|
||||
fi
|
||||
|
||||
rsync -av --delete --exclude-from="$EXCLUDE_FILE" "$SOURCE_DIR/" "$TARGET_DIR/"
|
||||
check_status "File sync (rsync)"
|
||||
|
||||
# Fix ownership and permissions
|
||||
print_status "Fixing ownership..."
|
||||
chown -R www-data:www-data "$TARGET_DIR/"
|
||||
check_status "Ownership fix (chown)"
|
||||
|
||||
# Step 3: Update database configuration
|
||||
print_status ""
|
||||
print_status "Step 3: Updating database configuration..."
|
||||
/usr/bin/python3 "$TARGET_DIR/sqlite/set_config.py"
|
||||
check_status "Database configuration update"
|
||||
|
||||
# Step 4: Check and fix file permissions
|
||||
print_status ""
|
||||
print_status "Step 4: Checking file permissions..."
|
||||
chmod +x "$TARGET_DIR/update_firmware.sh"
|
||||
chmod +x "$TARGET_DIR/update_firmware_from_file.sh"
|
||||
chmod 755 "$TARGET_DIR/sqlite/"*.py
|
||||
chmod 755 "$TARGET_DIR/NPM/"*.py
|
||||
chmod 755 "$TARGET_DIR/BME280/"*.py
|
||||
chmod 755 "$TARGET_DIR/SARA/"*.py
|
||||
chmod 755 "$TARGET_DIR/envea/"*.py
|
||||
chmod 755 "$TARGET_DIR/MPPT/"*.py 2>/dev/null
|
||||
chmod 755 "$TARGET_DIR/wifi/"*.py 2>/dev/null
|
||||
check_status "File permissions update"
|
||||
|
||||
# Step 5: Restart critical services
|
||||
print_status ""
|
||||
print_status "Step 5: Managing system services..."
|
||||
|
||||
services=(
|
||||
"nebuleair-npm-data.timer"
|
||||
"nebuleair-envea-data.timer"
|
||||
"nebuleair-sara-data.timer"
|
||||
"nebuleair-bme280-data.timer"
|
||||
"nebuleair-mppt-data.timer"
|
||||
"nebuleair-noise-data.timer"
|
||||
"nebuleair-wifi-powersave.timer"
|
||||
)
|
||||
|
||||
for service in "${services[@]}"; do
|
||||
if systemctl list-unit-files | grep -q "$service"; then
|
||||
if systemctl is-enabled --quiet "$service" 2>/dev/null; then
|
||||
print_status "Restarting enabled service: $service"
|
||||
systemctl restart "$service"
|
||||
if systemctl is-active --quiet "$service"; then
|
||||
print_status "✓ $service is running"
|
||||
else
|
||||
print_status "⚠ $service failed to start"
|
||||
fi
|
||||
else
|
||||
print_status "ℹ Service $service is disabled, skipping restart"
|
||||
fi
|
||||
else
|
||||
print_status "ℹ Service $service not found (may not be installed)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Step 6: System health check
|
||||
print_status ""
|
||||
print_status "Step 6: System health check..."
|
||||
|
||||
disk_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||
if [ "$disk_usage" -gt 90 ]; then
|
||||
print_status "⚠ Warning: Disk usage is high ($disk_usage%)"
|
||||
else
|
||||
print_status "✓ Disk usage is acceptable ($disk_usage%)"
|
||||
fi
|
||||
|
||||
if [ -f "$TARGET_DIR/sqlite/sensors.db" ]; then
|
||||
print_status "✓ Database file exists"
|
||||
else
|
||||
print_status "⚠ Warning: Database file not found"
|
||||
fi
|
||||
|
||||
# Cleanup logs > 10MB
|
||||
find "$TARGET_DIR/logs" -name "*.log" -size +10M -exec truncate -s 0 {} \;
|
||||
check_status "Log cleanup"
|
||||
|
||||
# Step 7: Cleanup temporary files
|
||||
print_status ""
|
||||
print_status "Step 7: Cleaning up temporary files..."
|
||||
rm -rf /tmp/nebuleair_update/
|
||||
check_status "Temp cleanup"
|
||||
|
||||
print_status ""
|
||||
print_status "======================================"
|
||||
print_status "Update from $OLD_VERSION to $NEW_VERSION completed successfully!"
|
||||
print_status "======================================"
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user