Skip to content

Instantly share code, notes, and snippets.

@raoulduke
Created March 5, 2026 06:51
Show Gist options
  • Select an option

  • Save raoulduke/c50c1b85017bd8edfc45647a040ebddb to your computer and use it in GitHub Desktop.

Select an option

Save raoulduke/c50c1b85017bd8edfc45647a040ebddb to your computer and use it in GitHub Desktop.
Raspberry Pi - Wireless network selection with LCD and keyboard
#!/usr/bin/env python3
import subprocess, time, fcntl, sys
from RPLCD.i2c import CharLCD
from ir.ui import read_key, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_ENTER, KEY_BACKSPACE, KEY_QUIT
LCD_I2C_ADDR = 0x27
LOCK_FILE = "/tmp/lcd.lock"
lcd = CharLCD(i2c_expander="PCF8574", address=LCD_I2C_ADDR, cols=16, rows=2, charmap="A00", auto_linebreaks=False)
def safe_lcd_write(lines):
try:
with open(LOCK_FILE, "a+") as lock:
fcntl.flock(lock, fcntl.LOCK_EX)
lcd.clear()
for i, line in enumerate(lines[:2]):
lcd.cursor_pos = (i, 0)
lcd.write_string(line[:16])
fcntl.flock(lock, fcntl.LOCK_UN)
except:
pass
def scan_wifi():
result = subprocess.run(["nmcli", "-t", "-f", "SSID,SIGNAL,SECURITY", "device", "wifi", "list"], capture_output=True, text=True)
networks = []
for line in result.stdout.splitlines():
parts = line.split(":")
if len(parts) < 2:
continue
ssid = parts[0]
if not ssid:
continue
try:
signal = int(parts[1])
except:
signal = 0
if signal > 0:
networks.append(ssid)
return list(dict.fromkeys(networks))
def network_has_config(ssid):
result = subprocess.run(["nmcli", "-t", "-f", "NAME", "connection", "show"], capture_output=True, text=True)
return ssid in result.stdout.splitlines()
def connect_existing(ssid):
subprocess.run(["nmcli", "connection", "up", ssid], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def connect_new(ssid, password):
subprocess.run(["nmcli", "dev", "wifi", "connect", ssid, "password", password], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def is_connected(ssid):
result = subprocess.run(["nmcli", "-t", "-f", "ACTIVE,SSID", "device", "wifi"], capture_output=True, text=True)
for line in result.stdout.splitlines():
parts = line.split(":")
if parts[0] == "yes" and parts[1] == ssid:
return True
return False
def select_network(networks):
index = 0
while True:
ssid = networks[index]
safe_lcd_write([ssid[:16], "<UP/DOWN ENTER>"])
key = read_key()
if key == KEY_UP:
index = (index - 1) % len(networks)
elif key == KEY_DOWN:
index = (index + 1) % len(networks)
elif key == KEY_ENTER:
return ssid
elif key == KEY_QUIT:
raise KeyboardInterrupt
def enter_password(ssid):
password = ""
while True:
safe_lcd_write([ssid[:16], password[-16:]])
key = read_key()
if key == KEY_LEFT: return None
if key == KEY_ENTER: return password
if key == KEY_BACKSPACE:
password = password[:-1]
elif key and len(key) == 1:
password += key
elif key == KEY_QUIT:
raise KeyboardInterrupt
def connect_flow(ssid):
while True:
if network_has_config(ssid):
safe_lcd_write(["Connecting...", ssid[:16]])
connect_existing(ssid)
if is_connected(ssid):
safe_lcd_write(["Connected", ssid[:16]])
time.sleep(2)
return
password = enter_password(ssid)
if password is None: return
safe_lcd_write(["Connecting...", ssid[:16]])
connect_new(ssid, password)
time.sleep(2)
if is_connected(ssid):
safe_lcd_write(["Connected", ssid[:16]])
time.sleep(2)
return
safe_lcd_write(["Wrong Password", "<- Back"])
key = read_key()
if key == KEY_LEFT:
return
elif key == KEY_QUIT:
raise KeyboardInterrupt
def main():
try:
while True:
networks = scan_wifi()
if not networks:
safe_lcd_write(["No WiFi found", ""])
time.sleep(3)
continue
ssid = select_network(networks)
connect_flow(ssid)
except KeyboardInterrupt:
lcd.clear()
sys.exit(0)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment