,
Cuando la Raspberry Pi está conectada a la red WiFi, es posible comunicarse con otros dispositivos de la red utilizando el protocolo UDP. Esto hace posible controlar la Raspberry Pi desde otro dispositivo o gestionar otros microcontroladores utilizando peticiones UDP. Se puede utilizar para enviar comandos y recibir datos de dispositivos Arduino, ESP32 o ESP8266 conectados a la misma red WiFi.
Hardware
- Raspberry Pi
- Conexión Wifi o Ethernet
Principio de funcionamiento
El Protocolo de Datagramas de Usuario (UDP) permite transmitir datagramas de forma rápida y sencilla entre dos dispositivos. Cada dispositivo se define mediante una dirección IP y un número de puerto. No es necesaria ninguna comunicación previa para establecer la conexión (en comparación con el handshaking).
La comunicación wifi utiliza generalmente una arquitectura cliente-servidor. En esta arquitectura, hay un servidor y uno o varios clientes. El servidor gestiona las peticiones de los clientes y puede enviarles una respuesta.
Código
Para comunicarnos utilizando el protocolo UDP, simplemente crearemos el servidor udp, que podrá leer y escribir en el puerto localPort. La biblioteca socket se utiliza para abrir una conexión entre dos dispositivos.
El constructor de socket espera dos parámetros, la familia de direcciones (en este caso direcciones de Internet) y el tipo de socket (en este caso UDP).
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) ## Internet,UDP
El socket debe estar enlazado a un puerto de la máquina sock.bind((hostname, localPort)). Poniendo un carácter vacío en lugar de hostname (equivalente a 0.0.0.0) permite enlazar el socket a todas las interfaces locales.
#!/usr/bin/env python # -*- coding: utf-8 -*- #Libraries import socket #https://wiki.python.org/moin/UdpCommunication #Parameters localPort=8888 bufferSize=1024 #Objects sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) ## Internet,UDP # function get_ip_address def get_ip_address(): """get host ip address""" ip_address = ''; s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8",80)) ip_address = s.getsockname()[0] s.close() return ip_address # function init def init(): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #enable broadcasting mode sock.bind(('', localPort)) print("UDP server : {}:{}".format(get_ip_address(),localPort)) # function main def main(): while True: data, addr = sock.recvfrom(bufferSize) # get data print("received message: {} form {}".format(data,addr)) sock.sendto("received OK",addr) # write data if __name__ == '__main__': init() main()
N.B.: La función get_ip_address() implementa un método para obtener la dirección IP de la Raspberry Pi abriendo un socket temporalmente. También puede utilizar la biblioteca os con el comando ifconfig.
Resultados
Para probar el resultado, utilizamos PacketSender, que actúa como cliente. Configuramos la interfaz para enviar un paquete UDP a la dirección 192.168.1.46 en el puerto 8888. En la interfaz podemos ver la respuesta «received OK» del servidor UDP.