Le callback WebSocket en Java

Le callback WebSocket en Java

La semaine passée nous avons publié une preview de la librairie Java et de la libraire Javascript avec le support WebSocket. Cette semaine nous allons reprendre notre exemple de lecteur de flux RSS en Java qui utilisait les callback HTTP et nous allons le modifier pour le rendre interactif grâce aux WebSockets.




La version originale de ce lecteur RSS utilise un Yocto-MaxiDisplay et un YoctoHub-Ethernet. Le YoctoHub-Ethernet est configuré pour utiliser un callback HTTP et se connecte périodiquement à un serveur Java. Le serveur récupère le contenu des flux RSS à afficher et crée une animation qui affiche le titre des articles les un après les autres. Cette animation est stockée dans la flash du Yocto-MaxiDisplay, et est affichée en boucle. Ce mécanisme fonctionne très bien mais il n'est pas interactif. L'utilisateur ne peut pas choisir quel flux afficher ni forcer le rafraîchissement des flux RSS.

Cette limitation est liée au fonctionnement du callback HTTP, qui se déroule en 4 temps:

  1. Ouverture de connexion
  2. Requête
  3. Réponse
  4. Fermeture de la connexion

Il n'est pas possible de garder la connexion ouverte et envoyer des commandes périodiquement, Les commandes envoyées par l'API Java sont donc obligatoirement interprétée par bloc. De plus, déclencher un callback dès qu'un bouton du Yocto-MaxiDisplay est pressé est possible, mais fonctionne mal car la latence lié à l'établissement de la connexion HTTP rend l'interface difficilement utilisable.

Utiliser les WebSockets


Fort heureusement ces limitations techniques n'existent pas avec les callback WebSocket. Grâce à eux, Il est désormais possible de maintenir indéfiniment une connexion bidirectionnelle entre le YoctoHub-Ethernet et le serveur Java .

Avec les WebSocket, l'API fonctionne de manière identique que ce soit en mode client ou en mode callback. Dans les deux cas les commandes sont transmises immédiatement au module Yoctopuce. Les notifications du YoctoHub sont aussi envoyées immédiatement à l'API. Pour résumer, hormis l'appel à RegisterHub() le même code peut être utilisé dans une simple application Java ou un callback.

Le code


La première étape consiste à écrire la classe qui va implémenter le endpoint qui répond à l'URL /wscallback. Lors de la connexion, la méthode onOpen() est exécutée par le serveur. Le code instancie l'objet WebSockRSSReader en lui passant la Session courante et exécute le code dans un Thread. Pour le serveur Java, c'est la seule méthode à implémenter. Il n'est pas nécessaire d'implémenter un message handler, car la librairie Yoctopuce s'en charge. La classe WebSockRSSReader contient tout la logique de notre application.


@ServerEndpoint("/wscallback")
public class WebSocketEndpoint
{
    @OnOpen
    public void onOpen(final Session session)
    {
        // on each connection start a new thread that will execute the code
        Thread thread = new Thread(new WebSockRSSReader(session));
        thread.start();
    }
}
 


Comme notre lecteur RSS est exécuté dans son propre thread, il faut créer son propre YAPIContext et utiliser celui ci au lieu des méthodes statiques de la classe YAPI. Comme pour le callback HTTP, les connections au serveur Java sont traitées dans le même processus. Cela implique que toutes les connexions partagent le même espace mémoire. Si on utilisait directement la classe YAPI, chaque connexion verrait les modules Yoctopuce des autres connexions simultanées. Utiliser son propre YAPIContext permet d’éviter que les modules d'une autre connexion ne viennent "polluer" notre inventaire. Un objet YAPIContext implémente les mêmes méthodes que YAPI, il suffit de remplacer les appels YAPI.xxx() par _yctx.xxx().

La première étape consiste à enregistrer le YoctoHub qui s'est connecté au serveur Java à l'aide de la méthode RegisterHubWebSocketCallback. Il faut lui passer la session de la connexion pour que la librairie puisse enregistrer les message handler. A partir de cet appel, il est possible d’utiliser l'API Yoctopuce sans limitation.


public class WebSockRSSReader implements Runnable
{

    private YAPIContext _yctx;
    private final Session _session;

    public WebSockRSSReader(Session session)
    {
        _session = session;
    }

    public void run()
    {
        _yctx = new YAPIContext();
        try {
            _yctx.RegisterHubWebSocketCallback(_session);
            setupYoctoDisplay();
            // run while WebSocket is connected
            while (_session.isOpen()) {
                if (checkForNewArticles()) {
                    refreshDisplay();
                }
                _yctx.Sleep(1000);
            }
        } catch (YAPI_Exception e) {
            e.printStackTrace();
        }
        _yctx.FreeAPI();
    }
    ...
 



Utiliser des callback dans un callback WebSocket


Comme la communication est bidirectionnelle, il possible d’enregistrer un callback java pour traiter de manière efficace le changement d’état des boutons.

La méthode setupYoctoDisplay initialise l'écran et enregistre un callback pour chaque bouton avec la méthode registerValueCallback. Ce callback est appelé dès qu'un bouton change d'état. Le callback change l'index de l'article à afficher et force le rafraîchissement de l’écran.


    private void setupYoctoDisplay() throws YAPI_Exception
    {
        _display = YDisplay.FirstDisplayInContext(_yctx);
        // reset screen
        _display.resetAll();

        YModule module = _display.module();
        String serial = module.get_serialNumber();

        YAnButton left = YAnButton.FindAnButtonInContext(_yctx,
                              serial + ".anButton1");
        left.registerValueCallback(new YAnButton.UpdateCallback()
        {
            public void yNewValue(YAnButton button, String value)
            {
                if (debounce(button, value) == 1) {
                    if (_itemIndex > 0) {
                        _itemIndex -= 1;
                        refreshDisplay();
                    }
                }
            }
        });
        //do the same for others buttons
        ...
    }
    ...
}
 


La méthode checkForNewArticles vérifie si les Flux RSS on été mis à jour et La méthode refreshDisplay affiche sur le Yocto-MaxiDisplay l'article à afficher. Le code ce cette application est disponible sur GitHub

  
Une petite démo



Conclusion


Les WebSockets permettent de s’affranchir des limitations du mode HTTP Callback. Il est désormais possible de réaliser des applications Yoctopuce élaborées en mode callback.

Commenter aucun commentaire
Retour au blog












Yoctopuce, get your stuff connected.