ESP32/reconfig_simple.py

168 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Simple ESP32 WiFi Reconfiguration Tool
Sends WiFi config to all connected ESP32 devices via serial
"""
import serial
import time
import glob
import argparse
import sys
def reconfig_devices(ssid, password, start_ip, gateway="192.168.1.1",
netmask="255.255.255.0", verbose=False):
"""Reconfigure all connected devices"""
devices = sorted(glob.glob('/dev/ttyUSB*'))
num_devices = len(devices)
if num_devices == 0:
print("ERROR: No devices found!")
return 0
# Parse start IP
ip_parts = start_ip.split('.')
ip_base = '.'.join(ip_parts[:3])
ip_start = int(ip_parts[3])
ok_devices = 0
print(f"Found {num_devices} devices")
print(f"SSID: {ssid}")
print(f"Password: {'*' * len(password)}")
print(f"IP Range: {ip_base}.{ip_start} - {ip_base}.{ip_start + num_devices - 1}")
print()
for idx, dev in enumerate(devices):
ip = f"{ip_base}.{ip_start + idx}"
print(f"[{idx:2d}] Configuring {dev:14s}{ip}", end='')
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(f"MASK:{netmask}\n".encode())
time.sleep(0.1)
ser.write(f"GW:{gateway}\n".encode())
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 verbose and response.strip():
print(f"\n Response: {response[:80]}")
if 'OK' in response:
print("")
ok_devices += 1
else:
print(" ⚠ (no OK)")
ser.close()
except Exception as e:
print(f" ✗ Error: {e}")
time.sleep(0.5)
print()
print(f"{'='*60}")
print(f"Success: {ok_devices}/{num_devices}")
print(f"Failed: {num_devices - ok_devices}/{num_devices}")
print(f"{'='*60}")
return ok_devices
def main():
parser = argparse.ArgumentParser(
description='Reconfigure WiFi settings on all connected ESP32 devices',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Basic usage with defaults
%(prog)s
# Custom IP range
%(prog)s --start-ip 192.168.1.100
# Custom WiFi credentials
%(prog)s -s MyNetwork -p mypassword
# Different subnet
%(prog)s --start-ip 10.0.0.50 -g 10.0.0.1
# Verbose mode
%(prog)s -v
"""
)
parser.add_argument('-s', '--ssid', default='ClubHouse2G',
help='WiFi SSID (default: ClubHouse2G)')
parser.add_argument('-p', '--password', default='ez2remember',
help='WiFi password (default: ez2remember)')
parser.add_argument('--start-ip', default='192.168.1.51',
help='Starting IP address (default: 192.168.1.51)')
parser.add_argument('-g', '--gateway', default='192.168.1.1',
help='Gateway IP (default: 192.168.1.1)')
parser.add_argument('-m', '--netmask', default='255.255.255.0',
help='Network mask (default: 255.255.255.0)')
parser.add_argument('-v', '--verbose', action='store_true',
help='Show device responses')
parser.add_argument('-w', '--wait', type=int, default=30,
help='Seconds to wait for connections (default: 30)')
args = parser.parse_args()
# Reconfigure all devices
ok_count = reconfig_devices(
ssid=args.ssid,
password=args.password,
start_ip=args.start_ip,
gateway=args.gateway,
netmask=args.netmask,
verbose=args.verbose
)
# Wait for connections
if ok_count > 0:
print(f"\nWaiting {args.wait}s for WiFi connections...")
time.sleep(args.wait)
print("Done!")
print()
print("Test commands:")
# Extract IP info
ip_parts = args.start_ip.split('.')
ip_base = '.'.join(ip_parts[:3])
ip_start = int(ip_parts[3])
num_devices = len(sorted(glob.glob('/dev/ttyUSB*')))
print(f" # Ping all devices")
print(f" for i in {{{ip_start}..{ip_start + num_devices - 1}}}; do ping -c 1 {ip_base}.$i & done; wait")
print()
print(f" # Check device status")
print(f" ./check_device_status.py --reset")
print()
print(f" # Test first device")
print(f" iperf -c {ip_base}.{ip_start}")
print()
sys.exit(0 if ok_count > 0 else 1)
if __name__ == '__main__':
main()