← Punto de acceso WiFi por botón en un Raspberry PLC
Seguidores solares de dos ejesRaspberry PLC 21WiFiGPIOInfraestructura
Punto de acceso WiFi por botón en un Raspberry PLC — ejemplo completo
Convierte un pulsador en un punto de acceso WiFi temporal en un Raspberry PLC 21 con nmcli e interrupciones GPIO, para configurar en campo sin redes.
Programa completo y ejecutable para el Raspberry PLC 21 (wifi-access-point-button.py): incluye cabecera de conexionado, requisitos y notas de integración.
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales
Vista de solo lectura.
#!/usr/bin/env python3
# -----------------------------------------------------------------------------
# COMPLETE EXAMPLE — WiFi access point activated by a physical button (nmcli)
#
# Device: Raspberry PLC 21 (Industrial Shields)
# Based on: dual-axis solar tracker project
#
# Requirements:
# pip3 install RPi.GPIO
# NetworkManager installed (nmcli) and service running
# Run as root or with permissions over nmcli (systemd service)
#
# Logic:
# A push button on PLC input I0.5 triggers a GPIO interrupt. The callback
# brings up a WiFi hotspot with nmcli (profile "hotspot") for 15 minutes,
# so the technician can connect with a phone/laptop to the tracker
# dashboard in the field, without any network infrastructure. After the
# timeout, the AP shuts down by itself so the network is not left exposed.
# SSID and password are placeholders: replace them on each installation.
# -----------------------------------------------------------------------------
import subprocess
import threading
import time
import RPi.GPIO as GPIO
INT_GPIO = 13 # BCM pin wired to PLC input I0.5
AP_SSID = "AP_SSID" # placeholder: hotspot SSID
AP_PASSWORD = "AP_PASSWORD" # placeholder: WPA2 key (min 8 characters)
AP_IFACE = "wlan0"
AP_TIMEOUT = 15 * 60 # 15 minutes of AP uptime
shutdown_timer = None # shutdown timer currently running
def nmcli(*args, timeout=15):
"""Runs nmcli and returns the CompletedProcess (no exception on failure)."""
return subprocess.run(["nmcli", *args], capture_output=True,
text=True, timeout=timeout)
def connection_exists(name):
"""True if a connection profile with that name already exists."""
res = nmcli("-t", "-f", "NAME", "connection", "show")
return name in res.stdout.splitlines()
def create_connection(name):
"""Creates the WPA2 hotspot profile with shared IP (AP mode)."""
nmcli("connection", "add", "type", "wifi", "ifname", AP_IFACE,
"con-name", name, "autoconnect", "no", "ssid", AP_SSID)
nmcli("connection", "modify", name,
"802-11-wireless.mode", "ap",
"802-11-wireless.band", "bg",
"ipv4.method", "shared",
"wifi-sec.key-mgmt", "wpa-psk",
"wifi-sec.psk", AP_PASSWORD)
print(f"Profile '{name}' created (SSID {AP_SSID})")
def start_ap():
"""Activates the hotspot and schedules its automatic shutdown."""
global shutdown_timer
if not connection_exists("hotspot"):
create_connection("hotspot")
res = nmcli("connection", "up", "hotspot", timeout=15)
if res.returncode == 0:
print(f"AP active for {AP_TIMEOUT // 60} min")
else:
print(f"Error bringing up the AP: {res.stderr.strip()}")
return
# Restart the timer if the button is pressed while the AP is already up.
if shutdown_timer:
shutdown_timer.cancel()
shutdown_timer = threading.Timer(AP_TIMEOUT, stop_ap)
shutdown_timer.daemon = True
shutdown_timer.start()
def stop_ap():
"""Shuts down the hotspot (end of the field configuration window)."""
nmcli("connection", "down", "hotspot")
print("AP down: end of configuration window")
def int_activated_callback(channel):
"""Button interrupt: simple debounce + AP startup."""
time.sleep(0.05) # debounce
if GPIO.input(INT_GPIO) == GPIO.LOW: # confirm a real press
print("Button pressed: bringing up access point")
start_ap()
def main():
GPIO.setmode(GPIO.BCM)
GPIO.setup(INT_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(INT_GPIO, GPIO.FALLING,
callback=int_activated_callback, bouncetime=300)
print(f"Waiting for a press on I0.5 (GPIO {INT_GPIO})...")
try:
while True:
time.sleep(1) # the interrupt does the work
except KeyboardInterrupt:
pass
finally:
stop_ap()
GPIO.cleanup()
print("GPIO released")
if __name__ == '__main__':
main()
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales