support scripts

This commit is contained in:
Bob 2025-11-11 14:57:56 -08:00
parent 2e3939a2b8
commit 289efa97a6
6 changed files with 693 additions and 0 deletions

66
DEPLOYMENT_GUIDE.md Normal file
View File

@ -0,0 +1,66 @@
# ESP32 Mass Deployment Scripts
Scripts for deploying, configuring, and testing multiple ESP32 devices in parallel.
## Scripts
### 1. `mass_deploy.sh` - Basic Deployment
Simple parallel flashing and configuration.
**Usage:**
```bash
chmod +x mass_deploy.sh
PASSWORD='your_wifi_password' ./mass_deploy.sh ~/Code/esp32/esp32-iperf
```
### 2. `mass_deploy_enhanced.sh` - Production Deployment (RECOMMENDED)
Enhanced version with retry logic and verification.
**Usage:**
```bash
chmod +x mass_deploy_enhanced.sh
# Basic usage
PASSWORD='your_wifi_password' ./mass_deploy_enhanced.sh ~/Code/esp32/esp32-iperf
# With custom settings
PASSWORD='mypass' \
SSID='MyNetwork' \
START_IP='192.168.1.100' \
./mass_deploy_enhanced.sh
```
**Environment Variables:**
- `PASSWORD` - WiFi password (required)
- `SSID` - WiFi SSID (default: ClubHouse2G)
- `START_IP` - Starting IP (default: 192.168.1.51)
- `MAX_RETRIES` - Retry attempts (default: 2)
- `VERIFY_PING` - Test after config (default: true)
### 3. `test_devices.sh` - Device Testing
Tests all deployed devices with iperf.
**Usage:**
```bash
chmod +x test_devices.sh
NUM_DEVICES=32 ./test_devices.sh
```
## Quick Start
```bash
# 1. Connect all ESP32 devices via USB
# 2. Deploy with one command
PASSWORD='your_wifi_pass' ./mass_deploy_enhanced.sh ~/Code/esp32/esp32-iperf
# 3. Test all devices
NUM_DEVICES=32 ./test_devices.sh
```
## Performance
**Before:** 60-90 minutes (sequential)
**After:** 15-20 minutes (parallel) ⚡
See DEPLOYMENT_GUIDE.md for full documentation.

70
QUICK_START.md Normal file
View File

@ -0,0 +1,70 @@
# ESP32 Mass Deployment - Quick Reference
## Files You Need
1. **mass_deploy_enhanced.sh** - Main deployment script (RECOMMENDED)
2. **test_devices.sh** - Testing script
3. **DEPLOYMENT_GUIDE.md** - Full documentation
## One-Line Deployment
```bash
PASSWORD='your_wifi_pass' ./mass_deploy_enhanced.sh ~/Code/esp32/esp32-iperf
```
## Common Commands
### Deploy 32 devices
```bash
PASSWORD='mypass' ./mass_deploy_enhanced.sh
```
### Test all devices
```bash
NUM_DEVICES=32 ./test_devices.sh
```
### Custom IP range
```bash
PASSWORD='mypass' START_IP='192.168.1.100' ./mass_deploy_enhanced.sh
```
### Different WiFi network
```bash
PASSWORD='newpass' SSID='NewNetwork' GATEWAY='192.168.2.1' START_IP='192.168.2.50' ./mass_deploy_enhanced.sh
```
## IP Address Scheme
Default: `192.168.1.51 + device_index`
- Device 0 → 192.168.1.51
- Device 1 → 192.168.1.52
- Device 31 → 192.168.1.82
## Time Savings
- **Old way:** 60-90 minutes for 32 devices
- **New way:** 15-20 minutes for 32 devices
- **Speedup:** 4-5x faster! ⚡
## Troubleshooting
**No devices found?**
```bash
ls /dev/ttyUSB* /dev/ttyACM*
sudo usermod -a -G dialout $USER # then logout/login
```
**Flash failed?**
```bash
BAUD_RATE=115200 PASSWORD='pass' ./mass_deploy_enhanced.sh
```
**Can't ping devices?**
- Check WiFi password
- Wait 30 seconds after deployment
- Verify network supports static IPs
**iperf connection refused?**
- Device still booting (wait 30s)
- Check logs: `cat /tmp/esp32_deploy_*.log`

126
mass_deploy.sh Executable file
View File

@ -0,0 +1,126 @@
#!/bin/bash
# ESP32 Mass Deployment Script
# Builds firmware once, then flashes and configures multiple devices in parallel
set -e
# Configuration
PROJECT_DIR="${1:-$PWD}"
SSID="${SSID:-ClubHouse2G}"
PASSWORD="${PASSWORD:-your_password_here}"
START_IP="${START_IP:-192.168.1.51}"
NETMASK="${NETMASK:-255.255.255.0}"
GATEWAY="${GATEWAY:-192.168.1.1}"
BAUD_RATE="${BAUD_RATE:-460800}"
# Parse starting IP
IFS='.' read -r -a IP_PARTS <<< "$START_IP"
IP_BASE="${IP_PARTS[0]}.${IP_PARTS[1]}.${IP_PARTS[2]}"
IP_START=${IP_PARTS[3]}
echo "=========================================="
echo "ESP32 Mass Deployment"
echo "=========================================="
echo "Project: $PROJECT_DIR"
echo "SSID: $SSID"
echo "IP Range: ${IP_BASE}.${IP_START}+"
echo "Gateway: $GATEWAY"
echo "Netmask: $NETMASK"
echo "=========================================="
# Step 1: Build firmware once
echo ""
echo "[1/3] Building firmware..."
cd "$PROJECT_DIR"
idf.py build
echo "✓ Build complete"
# Step 2: Find all connected ESP32 devices
echo ""
echo "[2/3] Detecting ESP32 devices..."
DEVICES=($(ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null || true))
if [ ${#DEVICES[@]} -eq 0 ]; then
echo "ERROR: No devices found!"
exit 1
fi
echo "Found ${#DEVICES[@]} device(s):"
for i in "${!DEVICES[@]}"; do
echo " [$i] ${DEVICES[$i]}"
done
# Step 3: Flash and configure in parallel
echo ""
echo "[3/3] Flashing and configuring devices..."
echo ""
flash_and_configure() {
local INDEX=$1
local DEVICE=$2
local IP_ADDR="${IP_BASE}.$((IP_START + INDEX))"
local LOG_FILE="/tmp/esp32_deploy_${INDEX}.log"
{
echo "=== Device $INDEX: $DEVICE ==="
echo "Target IP: $IP_ADDR"
# Flash
echo "Flashing..."
idf.py -p "$DEVICE" -b "$BAUD_RATE" flash 2>&1 | grep -E "(Connecting|Wrote|Hash|Hard resetting|ERROR)" || true
# Wait for boot
sleep 3
# Configure WiFi
echo "Configuring WiFi..."
{
echo "CFG"
echo "SSID:$SSID"
echo "PASS:$PASSWORD"
echo "IP:$IP_ADDR"
echo "MASK:$NETMASK"
echo "GW:$GATEWAY"
echo "DHCP:0"
echo "END"
} > "$DEVICE"
# Wait for OK response
sleep 2
echo "✓ Device $INDEX complete: $IP_ADDR"
} > "$LOG_FILE" 2>&1
# Show summary
echo "[Device $INDEX] ${DEVICES[$INDEX]}$IP_ADDR [DONE]"
}
# Export function and variables for parallel execution
export -f flash_and_configure
export PROJECT_DIR SSID PASSWORD IP_BASE IP_START NETMASK GATEWAY BAUD_RATE
# Launch parallel jobs
for i in "${!DEVICES[@]}"; do
flash_and_configure "$i" "${DEVICES[$i]}" &
done
# Wait for all background jobs
wait
echo ""
echo "=========================================="
echo "Deployment Complete!"
echo "=========================================="
echo ""
echo "Configured devices:"
for i in "${!DEVICES[@]}"; do
IP_ADDR="${IP_BASE}.$((IP_START + i))"
echo " ${DEVICES[$i]}$IP_ADDR"
done
echo ""
echo "Logs saved to: /tmp/esp32_deploy_*.log"
echo ""
echo "Test with: iperf -c ${IP_BASE}.${IP_START}"
echo ""

244
mass_deploy_enhanced.sh Executable file
View File

@ -0,0 +1,244 @@
#!/bin/bash
# ESP32 Mass Deployment Script (Enhanced)
# Features: parallel flashing, auto-retry, verification, progress tracking
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
PROJECT_DIR="${1:-$PWD}"
SSID="${SSID:-ClubHouse2G}"
PASSWORD="${PASSWORD:-}"
START_IP="${START_IP:-192.168.1.51}"
NETMASK="${NETMASK:-255.255.255.0}"
GATEWAY="${GATEWAY:-192.168.1.1}"
BAUD_RATE="${BAUD_RATE:-460800}"
MAX_RETRIES="${MAX_RETRIES:-2}"
VERIFY_PING="${VERIFY_PING:-true}"
# Parse starting IP
IFS='.' read -r -a IP_PARTS <<< "$START_IP"
IP_BASE="${IP_PARTS[0]}.${IP_PARTS[1]}.${IP_PARTS[2]}"
IP_START=${IP_PARTS[3]}
# Check for password
if [ -z "$PASSWORD" ]; then
echo -e "${RED}ERROR: WiFi password not set!${NC}"
echo "Usage: PASSWORD='your_wifi_pass' $0 [project_dir]"
echo ""
echo "Or set via environment:"
echo " export PASSWORD='your_wifi_pass'"
echo " export SSID='YourSSID' # Default: ClubHouse2G"
echo " export START_IP='192.168.1.51' # Default: 192.168.1.51"
echo " $0"
exit 1
fi
print_banner() {
echo ""
echo -e "${BLUE}=========================================="
echo "ESP32 Mass Deployment Tool"
echo -e "==========================================${NC}"
echo "Project: $PROJECT_DIR"
echo "SSID: $SSID"
echo "IP Range: ${IP_BASE}.${IP_START}+"
echo "Gateway: $GATEWAY"
echo "Netmask: $NETMASK"
echo "Verify: $VERIFY_PING"
echo -e "${BLUE}==========================================${NC}"
}
print_banner
# Step 1: Build firmware
echo ""
echo -e "${YELLOW}[1/4] Building firmware...${NC}"
cd "$PROJECT_DIR"
if ! idf.py build; then
echo -e "${RED}✗ Build failed!${NC}"
exit 1
fi
echo -e "${GREEN}✓ Build complete${NC}"
# Step 2: Detect devices
echo ""
echo -e "${YELLOW}[2/4] Detecting ESP32 devices...${NC}"
DEVICES=($(ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null || true))
if [ ${#DEVICES[@]} -eq 0 ]; then
echo -e "${RED}ERROR: No devices found!${NC}"
echo "Connect ESP32 devices via USB and try again."
exit 1
fi
echo -e "${GREEN}Found ${#DEVICES[@]} device(s):${NC}"
for i in "${!DEVICES[@]}"; do
IP_ADDR="${IP_BASE}.$((IP_START + i))"
echo " [$i] ${DEVICES[$i]}$IP_ADDR"
done
# Step 3: Flash and configure
echo ""
echo -e "${YELLOW}[3/4] Flashing and configuring...${NC}"
echo ""
flash_and_configure() {
local INDEX=$1
local DEVICE=$2
local IP_ADDR="${IP_BASE}.$((IP_START + INDEX))"
local LOG_FILE="/tmp/esp32_deploy_${INDEX}.log"
local STATUS_FILE="/tmp/esp32_status_${INDEX}"
{
for ATTEMPT in $(seq 1 $MAX_RETRIES); do
echo "=== Device $INDEX: $DEVICE (Attempt $ATTEMPT/$MAX_RETRIES) ==="
echo "Target IP: $IP_ADDR"
# Flash
echo "Flashing..."
if idf.py -p "$DEVICE" -b "$BAUD_RATE" flash 2>&1; then
echo "✓ Flash successful"
else
echo "✗ Flash failed on attempt $ATTEMPT"
if [ $ATTEMPT -eq $MAX_RETRIES ]; then
echo "FAILED" > "$STATUS_FILE"
exit 1
fi
sleep 2
continue
fi
# Wait for boot
sleep 3
# Configure WiFi
echo "Configuring WiFi..."
{
echo "CFG"
echo "SSID:$SSID"
echo "PASS:$PASSWORD"
echo "IP:$IP_ADDR"
echo "MASK:$NETMASK"
echo "GW:$GATEWAY"
echo "DHCP:0"
echo "END"
} > "$DEVICE" 2>/dev/null || true
# Wait for network
sleep 5
# Verify if requested
if [ "$VERIFY_PING" = "true" ]; then
echo "Verifying connectivity..."
if ping -c 2 -W 3 "$IP_ADDR" > /dev/null 2>&1; then
echo "✓ Ping successful"
echo "SUCCESS" > "$STATUS_FILE"
break
else
echo "✗ Ping failed on attempt $ATTEMPT"
if [ $ATTEMPT -eq $MAX_RETRIES ]; then
echo "PING_FAIL" > "$STATUS_FILE"
fi
fi
else
echo "SUCCESS" > "$STATUS_FILE"
break
fi
sleep 2
done
} > "$LOG_FILE" 2>&1
# Show result
if [ -f "$STATUS_FILE" ]; then
STATUS=$(cat "$STATUS_FILE")
if [ "$STATUS" = "SUCCESS" ]; then
echo -e "${GREEN}[Device $INDEX] ${DEVICES[$INDEX]}$IP_ADDR [OK]${NC}"
elif [ "$STATUS" = "PING_FAIL" ]; then
echo -e "${YELLOW}[Device $INDEX] ${DEVICES[$INDEX]}$IP_ADDR [FLASHED, NO PING]${NC}"
else
echo -e "${RED}[Device $INDEX] ${DEVICES[$INDEX]}$IP_ADDR [FAILED]${NC}"
fi
fi
}
export -f flash_and_configure
export PROJECT_DIR SSID PASSWORD IP_BASE IP_START NETMASK GATEWAY BAUD_RATE MAX_RETRIES VERIFY_PING
export RED GREEN YELLOW BLUE NC
# Clean old status files
rm -f /tmp/esp32_status_* /tmp/esp32_deploy_*.log
# Launch parallel jobs
for i in "${!DEVICES[@]}"; do
flash_and_configure "$i" "${DEVICES[$i]}" &
done
# Wait for completion
wait
# Step 4: Summary
echo ""
echo -e "${YELLOW}[4/4] Deployment Summary${NC}"
echo -e "${BLUE}==========================================${NC}"
SUCCESS_COUNT=0
FAILED_COUNT=0
PING_FAIL_COUNT=0
for i in "${!DEVICES[@]}"; do
IP_ADDR="${IP_BASE}.$((IP_START + i))"
STATUS_FILE="/tmp/esp32_status_${i}"
if [ -f "$STATUS_FILE" ]; then
STATUS=$(cat "$STATUS_FILE")
case "$STATUS" in
SUCCESS)
echo -e "${GREEN}${NC} ${DEVICES[$i]}$IP_ADDR"
((SUCCESS_COUNT++))
;;
PING_FAIL)
echo -e "${YELLOW}${NC} ${DEVICES[$i]}$IP_ADDR (no ping response)"
((PING_FAIL_COUNT++))
;;
*)
echo -e "${RED}${NC} ${DEVICES[$i]}$IP_ADDR (failed)"
((FAILED_COUNT++))
;;
esac
else
echo -e "${RED}${NC} ${DEVICES[$i]}$IP_ADDR (no status)"
((FAILED_COUNT++))
fi
done
echo -e "${BLUE}==========================================${NC}"
echo -e "Total: ${#DEVICES[@]} devices"
echo -e "${GREEN}Success: $SUCCESS_COUNT${NC}"
if [ $PING_FAIL_COUNT -gt 0 ]; then
echo -e "${YELLOW}Warning: $PING_FAIL_COUNT (flashed but no ping)${NC}"
fi
if [ $FAILED_COUNT -gt 0 ]; then
echo -e "${RED}Failed: $FAILED_COUNT${NC}"
fi
echo -e "${BLUE}==========================================${NC}"
echo ""
echo "Logs: /tmp/esp32_deploy_*.log"
echo ""
echo "Test commands:"
echo " iperf -c ${IP_BASE}.${IP_START}"
echo " for i in {${IP_START}..$((IP_START + ${#DEVICES[@]} - 1))}; do ping -c 1 ${IP_BASE}.\$i & done; wait"
echo ""
# Cleanup status files
rm -f /tmp/esp32_status_*
exit $FAILED_COUNT

52
reconfig_simple.py Executable file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
import serial
import time
import glob
SSID = "ClubHouse2G"
PASSWORD = "ez2remember"
START_IP = 51
devices = sorted(glob.glob('/dev/ttyUSB*'))
print(f"Found {len(devices)} devices\n")
for idx, dev in enumerate(devices):
ip = f"192.168.1.{START_IP + idx}"
print(f"[{idx}] Configuring {dev}{ip}")
try:
ser = serial.Serial(dev, 115200, timeout=1)
time.sleep(0.5) # Let serial port stabilize
# Send configuration
ser.write(b"CFG\n")
time.sleep(0.1)
ser.write(f"SSID:{SSID}\n".encode())
time.sleep(0.1)
ser.write(f"PASS:{PASSWORD}\n".encode())
time.sleep(0.1)
ser.write(f"IP:{ip}\n".encode())
time.sleep(0.1)
ser.write(b"MASK:255.255.255.0\n")
time.sleep(0.1)
ser.write(b"GW:192.168.1.1\n")
time.sleep(0.1)
ser.write(b"DHCP:0\n")
time.sleep(0.1)
ser.write(b"END\n")
# Wait for OK response
time.sleep(0.5)
response = ser.read(100).decode('utf-8', errors='ignore')
if 'OK' in response:
print(f" ✓ Got OK response")
ser.close()
except Exception as e:
print(f" ✗ Error: {e}")
time.sleep(0.5)
print("\nWaiting 30s for connections...")
time.sleep(30)
print("Done! Test with: NUM_DEVICES=31 ./test_devices.sh")

135
test_devices.sh Executable file
View File

@ -0,0 +1,135 @@
#!/bin/bash
# ESP32 Device Testing Script
# Tests all deployed ESP32 devices with iperf
# Configuration
START_IP="${START_IP:-192.168.1.51}"
NUM_DEVICES="${NUM_DEVICES:-10}"
IPERF_TIME="${IPERF_TIME:-5}"
PROTOCOL="${PROTOCOL:-tcp}" # tcp or udp
# Parse starting IP
IFS='.' read -r -a IP_PARTS <<< "$START_IP"
IP_BASE="${IP_PARTS[0]}.${IP_PARTS[1]}.${IP_PARTS[2]}"
IP_START=${IP_PARTS[3]}
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}=========================================="
echo "ESP32 Device Testing"
echo -e "==========================================${NC}"
echo "IP Range: ${IP_BASE}.${IP_START} - ${IP_BASE}.$((IP_START + NUM_DEVICES - 1))"
echo "Protocol: $PROTOCOL"
echo "Duration: ${IPERF_TIME}s per device"
echo -e "${BLUE}==========================================${NC}"
echo ""
test_device() {
local INDEX=$1
local IP_ADDR="${IP_BASE}.$((IP_START + INDEX))"
local RESULT_FILE="/tmp/iperf_result_${INDEX}.txt"
# Test ping
if ! ping -c 1 -W 2 "$IP_ADDR" > /dev/null 2>&1; then
echo -e "${RED}✗ Device $INDEX ($IP_ADDR): No ping response${NC}"
echo "FAIL" > "$RESULT_FILE"
return 1
fi
# Test iperf
if [ "$PROTOCOL" = "udp" ]; then
IPERF_CMD="iperf -c $IP_ADDR -u -b 100M -t $IPERF_TIME"
else
IPERF_CMD="iperf -c $IP_ADDR -t $IPERF_TIME"
fi
if OUTPUT=$($IPERF_CMD 2>&1); then
# Extract bandwidth
BANDWIDTH=$(echo "$OUTPUT" | grep -oP '\d+(\.\d+)?\s+(K|M|G)bits/sec' | tail -1)
echo -e "${GREEN}✓ Device $INDEX ($IP_ADDR): $BANDWIDTH${NC}"
echo "SUCCESS:$BANDWIDTH" > "$RESULT_FILE"
else
echo -e "${RED}✗ Device $INDEX ($IP_ADDR): iperf failed${NC}"
echo "FAIL" > "$RESULT_FILE"
return 1
fi
}
export -f test_device
export IP_BASE IP_START IPERF_TIME PROTOCOL GREEN RED YELLOW BLUE NC
# Clean old results
rm -f /tmp/iperf_result_*.txt
# Quick ping test first
echo -e "${YELLOW}Quick connectivity check...${NC}"
for i in $(seq 0 $((NUM_DEVICES - 1))); do
IP_ADDR="${IP_BASE}.$((IP_START + i))"
if ping -c 1 -W 1 "$IP_ADDR" > /dev/null 2>&1; then
echo -n "."
else
echo -n "x"
fi
done
echo ""
echo ""
# Run iperf tests in parallel (batches of 4 to avoid overwhelming network)
echo -e "${YELLOW}Running iperf tests...${NC}"
BATCH_SIZE=4
for BATCH_START in $(seq 0 $BATCH_SIZE $((NUM_DEVICES - 1))); do
for i in $(seq $BATCH_START $(( BATCH_START + BATCH_SIZE - 1 ))); do
if [ $i -lt $NUM_DEVICES ]; then
test_device "$i" &
fi
done
wait
done
# Summary
echo ""
echo -e "${BLUE}=========================================="
echo "Test Summary"
echo -e "==========================================${NC}"
SUCCESS=0
FAILED=0
TOTAL_BANDWIDTH=0
for i in $(seq 0 $((NUM_DEVICES - 1))); do
RESULT_FILE="/tmp/iperf_result_${i}.txt"
if [ -f "$RESULT_FILE" ]; then
RESULT=$(cat "$RESULT_FILE")
if [[ "$RESULT" == SUCCESS:* ]]; then
((SUCCESS++))
else
((FAILED++))
fi
else
((FAILED++))
fi
done
echo "Tested: $NUM_DEVICES devices"
echo -e "${GREEN}Success: $SUCCESS${NC}"
if [ $FAILED -gt 0 ]; then
echo -e "${RED}Failed: $FAILED${NC}"
fi
SUCCESS_RATE=$(awk "BEGIN {printf \"%.1f\", ($SUCCESS / $NUM_DEVICES) * 100}")
echo "Rate: ${SUCCESS_RATE}%"
echo -e "${BLUE}==========================================${NC}"
# Cleanup
rm -f /tmp/iperf_result_*.txt
if [ $FAILED -gt 0 ]; then
exit 1
fi