En esta práctica implementaremos un servicio de mqtt que nos permitirá comunicarnos con la raspberry
pi por internet mediante una suscripción de un tópico a un servidor.
La ventaja que nos proporciona este método es que no tenemos necesariamente que tener todos los
dispositivos dentro de la misma red para que se puedan ver y comunicarse entre sí.
Por lo que podemos usar un módulo LTE de para enlazar la raspberry con una estación base.
¿Qué es MQTT?
MQTT o Message Queuing Telemetry Transport es un protocolo de
comunicación que transmite cadenas de texto, es ampliamente utilizado en entornos IOT, servicios de
mensajería,... tiene muchas aplicaciones
para trabajar como API, ya que al permitir el envió de hipertexto, podemos enviar cadenas JSON, XML,
...
Su funcionamiento se basa en un servidor central dónde se crean brokers que gestionan tópicos por los
que fluye la información. Los clientes se subscriben a estos tópicos y pueden hacer pulls
obteniendo la información
Kafka:
Kafka es el protocolo hermano, tiene un funcionamiento
similar con diferencia de que se crean logs de todos los mensajes y estos son consumidos de forma
predeterminada secuencialmente. Todo y que se puede configurar a gusto del desarrollador.
Uno de los beneficios es que a parte de mantener un registro, si por algún motivo la conexión se
pierde, al volver a establecerse esta, se puede continuar en el hilo dónde se había dejado. También
destacar que tiene una mayor escalabilidad y throughput. Fué desarrollada por
LindedIn y es el motor de streaming de Netflix.
Aunque en el proyecto no se ve, me pareció interesante mencionarlo ya que es una opción de cara a
futuros cursos.
Configuración del módulo LTE:
Para instalar el módulo es tan simple cómo seguir los siguientes pasos:
una vez conectado el usb, se puede comprobar si este dispositivo se ha instalado correctamente
usando al comanda
lusb
Luego insertar estos comandos secuencialmente:
sudo apt install minicom -y
minicom -D /dev/ttyUSB2 -b 115200
Luego escribir AT en ese terminal y esperar que aparezca un OK.
Finalmente escribir
AT+QCFG="usbnet",1
y la instalación ya estría.
Podemos comprobar lo anterior empleando cualquiera los comandos
ifcongfig
ip adress show
La prueba definitiva consiste en realizar un ping a cualquier servidor, por ejemplo a goolge.com
forzando la salida por esa interfície:
ping -I usb0 google.com -c 5
Demostración Tecnológica del servicio MQTT:
Para esta demostración, se implementará un servicio de telemetía de tal forma que seamos capaces de
recibir información del estado del rover. El código contará de dos partes: El cliente Rover y el
cliente suscrito a ese tópico.
ROVER:
import paho.mqtt.client as mqtt
import time
from datetime import datetime
import dronekit
#####Base de la que se parte para mandar telemetría del rover al PC
connection_string = "tcp:127.0.0.1:5762"
vehicle = dronekit.connect(connection_string, wait_ready=True, baud=115200)
broker = "test.mosquitto.org"
client =mqtt.Client("Sutton")
client.connect(broker)
print("Server connected")
topic = "excedida/mitologica"
while True:
now = datetime.now()
tiempo = now.strftime("%H:%M:%S")
pos = str(vehicle.location.global_frame)
mag = tiempo + ", " + pos
print(mag)
client.publish(topic, mag)
time.sleep(1)
Cliente suscrito:
import paho.mqtt.client as mqtt
import time
def message(client,userdata,message):
print("message topic: ", message.topic)
print("message: ", str(message.payload.decode("utf-8")))
topic = "excedida/mitologica"
broker = "test.mosquitto.org"
client=mqtt.Client("BlingBling")
client.connect(broker)
client.subscribe(topic)
print("broker connected")
client.on_message = message
client.loop_start()
integración del código:
Gracias a las buenas praxis empleadas a lo largo del proyecto y la arquitectura modular, ha sido
relativamente sencillo realizar la integración, ya que todas las funciones requeridas ya se
encoraban
previamente desarrolladas y solo ha sido necesario realizar un cambio en el main cambiando
la función controller() por listerner_mqtt_control(), ambas
pasándoles como argumento un objeto dronekit.vehichle.
El código de esta función es el siguiente:
from control import *
import paho.mqtt.client as mqtt
import signal
def listerner_mqtt_control(vehicle):
def command(client,userdata,cmd):
cmd = str(cmd.payload.decode('utf-8'))
print(cmd)
if cmd == 'arm':
arm_rover(vehicle)
elif cmd == 'disarm':
DISarm_rover(vehicle)
elif cmd == 'AP':
controller(vehicle)
topic = "excedida/control"
broker = "test.mosquitto.org"
client =mqtt.Client("Sutton")
client.connect(broker)
client.subscribe(topic)
client.on_message = command
client.loop_forever()
Importante fijarse en el client.loop_forever(), ya que permite estar continuamente consumiendo
el tópico de forma óptima.
Estación de control:
Por otro lado, se ha diseñado una aplicación para poder controlar el rover mediante la comunicación
MQTT, con una interfaz gráfica sencilla:
import paho.mqtt.client as mqtt
import time
from datetime import datetime
import dronekit
from tkinter import *
broker = "test.mosquitto.org"
client =mqtt.Client("LuzDeGas")
client.connect(broker)
print("Server connected")
topic = "excedida/control"
def ARM():
print('vehicle armed')
client.publish(topic,'arm')
def DARM():
print('vehicle dissarmed')
client.publish(topic,'disarm')
def AP():
print('Autopilot engaged')
client.publish(topic,'AP')
frame = Tk()
frame.title('Panel de control del ROVER')
frame.minsize(300,200)
blank0 = Label(frame, text='\t')
blank0.grid(row=0,column=2)
blank1 = Label(frame, text='\t')
blank1.grid(row=1,column=3)
blank2 = Label(frame, text='\t')
blank2.grid(row=1,column=5)
boton1 = Button(frame, text='ARM', command=ARM, bg='green')
boton1.grid(row=1, column=2)
boton2 = Button(frame, text='D/ARM', command=DARM, bg='red')
boton2.grid(row=1,column=4)
boton3 = Button(frame, text='AP',bg='yellow', command=AP)
boton3.grid(row=1, column=6)
frame.mainloop()
El resultado final del diseño e implementación se puede ver en el vídeo a continuación. No se ha podido
probar en la plataforma física ya que estos días son festivos y no tengo acceso físico al ROVER: