support scripts
This commit is contained in:
parent
2e3939a2b8
commit
289efa97a6
|
|
@ -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.
|
||||||
|
|
@ -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`
|
||||||
|
|
@ -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 ""
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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")
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue