168 lines
4.9 KiB
Python
Executable File
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()
|