/ RNode_Firmware_CE_G2 / configure_wifi.py
configure_wifi.py
1 #!/usr/bin/env python3 2 """ 3 Configure WiFi on RNode devices with HAS_WIFI (e.g. Station G2). 4 Sends KISS commands to set SSID, password, and enable STA mode. 5 Usage: python3 configure_wifi.py /dev/ttyACM0 "MySSID" "MyPassword" 6 """ 7 8 import sys 9 import time 10 import serial 11 12 FEND = 0xC0 13 FESC = 0xDB 14 TFEND = 0xDC 15 TFESC = 0xDD 16 17 CMD_WIFI_MODE = 0x6A 18 CMD_WIFI_SSID = 0x6B 19 CMD_WIFI_PSK = 0x6C 20 21 WR_WIFI_OFF = 0x00 22 WR_WIFI_STA = 0x01 # Connect to existing network 23 WR_WIFI_AP = 0x02 # Create hotspot 24 25 26 def escape(data: bytes) -> bytes: 27 data = data.replace(bytes([FESC]), bytes([FESC, TFESC])) 28 data = data.replace(bytes([FEND]), bytes([FESC, TFEND])) 29 return data 30 31 32 def send_kiss_wifi(ser: serial.Serial, cmd: int, data: bytes) -> None: 33 """Send a KISS WiFi command. Data is null-terminated for SSID/PSK.""" 34 frame = bytes([FEND, cmd]) + escape(data) + bytes([FEND]) 35 ser.write(frame) 36 time.sleep(0.05) 37 38 39 def configure_wifi(port: str, ssid: str, password: str, mode: int = WR_WIFI_STA) -> bool: 40 if len(ssid) > 32: 41 print("SSID must be 32 characters or fewer") 42 return False 43 if len(password) > 32: 44 print("Password must be 32 characters or fewer") 45 return False 46 47 try: 48 ser = serial.Serial(port, 115200, timeout=2) 49 except serial.SerialException as e: 50 print(f"Failed to open {port}: {e}") 51 return False 52 53 print("Configuring WiFi...") 54 time.sleep(0.5) 55 56 # 1. Set SSID (null-terminated; firmware pads to 32 bytes) 57 ssid_data = ssid.encode("utf-8") + b"\x00" 58 send_kiss_wifi(ser, CMD_WIFI_SSID, ssid_data) 59 print(f" SSID set: {ssid}") 60 61 # 2. Set password (null-terminated; firmware pads to 32 bytes) 62 psk_data = password.encode("utf-8") + b"\x00" 63 send_kiss_wifi(ser, CMD_WIFI_PSK, psk_data) 64 print(" Password set") 65 66 # 3. Enable STA mode (connect to network) 67 send_kiss_wifi(ser, CMD_WIFI_MODE, bytes([mode])) 68 mode_name = "STA (connect to network)" if mode == WR_WIFI_STA else "AP (hotspot)" if mode == WR_WIFI_AP else "off" 69 print(f" WiFi mode: {mode_name}") 70 71 ser.close() 72 print("\nDone. The RNode will connect to your network.") 73 print("Check the display for the assigned IP, or use rnodeconf -i after reconnecting.") 74 return True 75 76 77 def main(): 78 if len(sys.argv) < 4: 79 print(__doc__) 80 print("Arguments: PORT SSID PASSWORD") 81 print('Example: python3 configure_wifi.py /dev/ttyACM0 "MyNetwork" "MySecretPass"') 82 sys.exit(1) 83 84 port = sys.argv[1] 85 ssid = sys.argv[2] 86 password = sys.argv[3] 87 88 if not configure_wifi(port, ssid, password): 89 sys.exit(1) 90 91 92 if __name__ == "__main__": 93 main()