Comunicación Serie con Arduino (II)


f6ripaphqf9h5io-medium

Anteriormente vimos el ejemplo mínimo de un cliente para Arduino. En este post, se desarrollará el servidor de ese mismo ejemplo, escrito en Python para PC. En este caso, se utilizará el endpoint serie para Ice.

Python: servidor mínimo

Recordando la entrada anterior, tenías una interfaz Ice muy sencilla, definida en el fichero example.ice. También habías implementado un cliente para Arduino que usaba esa misma interfaz. El cliente mandaba una invocación al método sayHello cada segundo. En este post, implementarás el servidor en Python que recibirá esas invocaciones.

Nota: puedes descargarte todo el código fuente y los archivos de configuración para este ejemplo (y los demás de esta serie de artículos) desde el repositorio de bitbucket:

hg clone https://bitbucket.org/arco_group/arduino-icec-idm

Para realizar esta parte correctamente, dirígete al directorio que habías creado, llamado hello-world. Allí, genera un fichero para el servidor (por ejemplo server.py). Incluye en él el siguiente boilerplate:

import Ice
import sys

class Server(Ice.Application):
    def run(self, args):
        ic = self.communicator()

if __name__ == "__main__":
    Server().main(sys.argv)

Este código es un esqueleto básico muy común en aplicaciones de Ice. Si lo ejecutas con el intérprete de Python, se lanzará correctamente, aunque no hará básicamente nada, y terminará:

python server.py

Añadir soporte para el Endpoint Serie

Ice, por defecto, solo proporciona soporte a los endpoints que trae de serie (TCP, UDP, SSL y WS). Para poder utilizar el endpoint serie, será necesario que configures el broker adecuadamente. Para ello se emplea un fichero de configuración (puedes llamarlo, por ejemplo, server.config), que contendrá lo siguiente:

Ice.Plugin.PyEndpoint = IcePyEndpoint:addPyEndpointSupport
PyEndpoint.Module = SerialEndpoint
PyEndpoint.Factory = EndpointFactoryI

Ahora podrás ejecutar de nuevo el servidor, especificando que la configuración del broker la debe tomar de ese fichero (aunque seguirá sin hacer gran cosa):

python server.py --Ice.Config=server.config

Instanciando el objeto Server

El servidor deberá crear un objecto (llamado Server) que implementará la interfaz Hello,  y hacerlo disponible a través del puerto serie. Para ello, como primer paso, necesitas importar la interfaz (en el ámbito global del fichero):

Ice.loadSlice("example.ice")
import Example

Lo siguiente será implementar el sirviente. Para este ejemplo, puedes simplemente imprimir por consola que la invocación ha llegado. Recuerda que el sirviente hereda de la interfaz Example.Hello, por lo que puedes definir la siguiente clase (a nivel global también) :

class HelloI(Example.Hello):
    def sayHello(self, current):
        print("sayHello was called!")

Por último, tendrás que crear el adaptador de objetos (con el endpoint serie), y añadir este sirviente. El código (incluido en el método run de la clase Server) será el siguiente:

adapter = ic.createObjectAdapterWithEndpoints(
    "Adapter", "serial -h 127.0.0.1 -p 1793")
adapter.activate()
adapter.add(
    HelloI(),
    ic.stringToIdentity("Server")
)

print("Waiting events...")
self.shutdownOnInterrupt()
ic.waitForShutdown()

De todo ese código, llama la atención especialmente el endpoint del adaptador:

serial -h 127.0.0.1 -p 1793

Dado que este endpoint debe utilizar el puerto serie como mecanismo de comunicaciones, ¿qué significan los dos parámetros -h y -p en este caso? ¿Y dónde especificas el dispositivo serie que deseas emplear? La siguiente sección analizará esto en detalle.

Servicio de acceso al puerto serie

La comunicación serie con cualquier dispositivo se considera como un enlace punto a punto. Por las características específicas de este tipo de puertos, se requiere que el acceso a este dispositivo sea exclusivo. Esto implica que dos servicios (o el mismo servicio desde dos puntos diferentes) no puedan utilizar concurrentemente el mismo puerto serie. Eso supone una gran desventaja, pues evita (por ejemplo) que un mismo servicio pueda actuar como cliente y servidor al mismo tiempo (debido a la arquitectura del endpoint).

Para solucionar este problema, se ha diseñado un servicio que actúa como árbitro de acceso al medio, serializando y distribuyendo los mensajes entre los clientes y el dispositivo. Este servicio (llamado SerialService) es accesible mediante una conexión TCP.

El servicio SerialService está incluido en el paquete ice-serial. Para lanzarlo necesitas, de nuevo, un fichero de configuración (que puedes llamar serial-service.config). En este caso, el contenido será el siguiente:

SerialService.Device = /dev/ttyUSB0
SerialService.Speed = 115200
SerialService.Host = 127.0.0.1
SerialService.Port = 1793

Esta configuración asume que el puerto serie está disponible en el fichero /dev/ttyUSB0, pero puedes cambiarlo para adaptarlo a tus circunstancias. Por otro lado, vemos que escucha en la interfaz 127.0.0.1, en el puerto TCP 1793, que se corresponde con la configuración que pusiste en el endpoint serie del adaptador de objetos.

Una vez creado el fichero de configuración, puedes ejecutar el servicio con el comando:

serial-service --Ice.Config=serial-service.config

Ejecución y prueba del servidor

Si tienes el servicio SerialService funcionando correctamente, ya puedes ejecutar el servidor de ejemplo, de la siguiente forma:

python server.py --Ice.Config=server.config

Además, si tienes conectado el Arduino al puerto serie indicado, y subiste el sketch que vimos en la anterior entrada, deberías ver el mensajesayHello was called!‘ en la consola del servidor, una vez por segundo. Si así es, ¡enhorabuena! 😉

screenshot-from-2016-10-17-12-51-49
Ejecución del servidor

 

 

 

 

 

 

Advertisements

2 thoughts on “Comunicación Serie con Arduino (II)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s