#!/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