Optimiser les communications avec les modules Yoctopuce

Optimiser les communications avec les modules Yoctopuce

Les utilisateurs chevronnés des modules Yoctopuce se posent tôt ou tard la question de la quantité de données transférée pour récupérer les mesures des capteurs Yoctopuce. Cela peut être aussi bien pour optimiser la consommation GSM, comme expliqué dans un précédent article, mais aussi simplement pour améliorer les performances d'une application où les modules sont connectés par USB mais les mesures doivent être lues à très rapidement. Voilà donc une explication détaillée pour tout savoir et tout optimiser...

Protocole de base


Le fonctionnement élémentaire de tous les modules Yoctopuce est de recevoir des requêtes au format HTTP et de répondre avec des données au format JSON, comprenant l'état et les paramètres de toutes les fonctions du capteurs. Ce fonctionnement s'applique de manière non seulement pour les communications à travers le réseau, où ces protocoles sont très usuels, maus aussi aux communications par USB, dans quel cas les messages HTTP/JSON sont encapsulés dans des trames USB.

L'avantage de cette solution est qu'elle permet une très grande souplesse sur le genre et la forme des données fournies par les modules. Par exemple, un programme destiné à contrôler la température mis en service il y a 5 ans pourra fonctionner aujourd'hui avec des capteurs qui n'existaient pas à l'époque, ou dont les fonctionnalités ont été étendues depuis par de nouveaux firmware, sans poser de problème de compatibilité.

Le désavantage de cette solution assez simple est qu'elle est assez verbeuse: si le but n'est que de lire la valeur d'un capteur, la quantité de données transférée à chaque lecture de tout l'état peut paraître exagérée. Cela n'a aucune importance si on veut lire un capteur à travers USB une fois par seconde ou moins, car l'échange ne prend que quelques centièmes de seconde, mais dans certains cas cela peut poser problème.

Nous proposons donc différents mécanisme éviter la pénalité du transfert de données, qui sont documentés ci-dessous. A vous de choisir celui qui convient le mieux à votre applications...

Mémoire cache de la librairie


Lorsque l'on lit plusieurs valeurs sur le même module Yoctopuce, par exemple pour lire les six entrées d'un Yocto-MaxiThermistor, l'échange de données ne se produit que lors de la première lecture. Toutes les valeurs sont à ce moment stockées dans la mémoire cache de la librairie, pour être fournies ensuite instantanément. La durée de validité de cette mémoire cache est normalement de 5 ms. Si vous avez besoin d'augmenter cette durée pour limiter encore plus les communications, vous pouvez utiliser la méthode YAPI.SetCacheValidity():

  YAPI.SetCacheValidity(100);


Par contre, cette solution ne vous permettra pas d'augmenter la fréquence des lectures.

Lecture d'un attribut unique


Il est aussi possible de lire explicitement un seul attribut d'un capteur, à la place de transférer tout l'état du module. Cela peut se fait à l'aide de la méthode loadAttribute(), comme nous vous l'avions démontré dans un précédent article:

  sensor.loadAttribute("unit");


C'est efficace s'il n'y a qu'une ou deux valeurs à lire, mais si ces requêtes sont nombreuses, la pénalité de répéter les requêtes se fera sentir.

Lecture par callback


La lecture des capteurs par callback, décrite dans ce précédent article restera toujours la manière la plus efficace de lire des capteurs. Elle permet le transfert sélectif et spontané du strict minimum de données désiré, sans pénalité d'encapsulation au format HTTP ou JSON. Les capteurs Yoctopuce offrent le choix de callbacks à chaque changement de valeur, ou de callbacks périodiques à intervalle prédéfinis:

  lightSensor.registerValueCallback(myValueChangeCallbackFunction);

  tempSensor.set_reportFrequency("15/m");
  tempSensor.registerTimedReportCallback(myPeriodicCallbackFunction);


Cette méthode est nettement plus efficace que les lectures explicites, aussi bien pour un fonctionnement à travers USB que par le réseau.

Lecture par énumération des fonctions


Si vous n'êtes pas à l'aise avec les fonctions de callbacks, il existe une méthode alternative permettant d'obtenir à tout moment la valeur du dernier changement de valeur signalé, sans causer d'échange d'information supplémentaire: l'énumération des fonctions du module. En effet, la librairie Yoctopuce mémorise implicitement la dernière valeur de chaque mesure, et on peut les récupérer à l'aide des fonctions functionValue() sans le moindre coût de communication:

  string serial = module.get_serialNumber();
  for (int i = 0; i < module.functionCount(); i++) {
    string hardwareId = serial + "." + module.functionId(i);
    Console.WriteLine(hardwareId + ": " + module.functionValue(i));
  }



Callback de changement de configuration


La seule limitation de la lecture par callback (ou par énumération des fonctions) décrite ci-dessus est qu'elle se limite à la valeur mesurée des capteurs, et ne permet pas de surveiller ses attributs auxiliaires comme l'unité ou les paramètres de calibration. Pour éviter de devoir réintroduire des accès périodiques inutiles avec le protocole de base, il est désormais possible d'enregistrer aussi une fonction de callback qui sera appelée chaque fois qu'un changement de configuration est détecté sur un module. Ainsi, l'application peut aller sélectivement recharger la configuration des capteurs (unité, etc.), même si elle a été changée indépendamment par une autre application:

  tempSensor.registerConfigChangeCallback(myConfigChangeCallbackFunction);



Inventaire des modules et Plug-and-Play


En plus du trafic de données nécessaire à la lecture des capteurs, il y a un trafic auxiliaire nécessaire à l'énumération des modules connectés et à la gestion du plug-and-play. Ce trafic est négligeable sur USB, mais il est significatif dans le cas de connections à travers le réseau.

En principe, chaque connexion et déconnexion de module sur un hub réseau est signalé par un événement, qui déclenche un callback d'arrivée ou de déconnexion de module. L'application appelle périodiquement YAPI.UpdateDeviceList() pour en être informée, via les callbacks dédiés (voir cet article).

Néanmoins, pour s'assurer de ne jamais manquer un événement de connexion ou de déconnexion, une fois toutes les dix secondes, les appels à YAPI.UpdateDeviceList() déclenchent un transfert complet de la liste de tous les modules connectés et de chacune de leurs fonctions. Le coût de ce transfert est négligeable sur un réseau local, mais peut être significatif si les performances comptent ou sur une ligne GSM. Dans ces cas, si l'on attend peu ou pas de changement de modules, ou lorsque l'on n'a pas de raison d'anticiper des pertes de notifications de connexion et déconnexion, il est recommandé d'augmenter la durée de validité de l'inventaire des modules à une heure ou plus, à l'aide de la méthode YAPI.SetDeviceListValidity():

  YAPI.SetDeviceListValidity(3600);


Ainsi, le trafic auxiliaire sera lui aussi réduit au strict minimum.

Versions des firmwares et des librairies


Les méthodes registerConfigChangeCallback, SetDeviceListValidity et SetCacheValidity sont disponibles à partir de la révision 31701 de nos librairies de programmation.

Pour utiliser les callbacks de changement de configuration, il faut aussi vous assurer d'utiliser des firmwares (et le cas échéant d'un VirtualHub) en révision 31745 ou plus récent.

Pour résumer


Pour une réduction maximale des données transmises sur le réseau:

  • Relisez l'article sur la consommation de données
  • Utilisez une lecture par callback périodique:
    sensor.registerTimedReportCallback()
  • Désactivez l'envoi des valeurs instantanées:
    sensor.muteValueCallbacks()
  • Allongez la durée de validité de l'inventaire des modules:
    YAPI.SetDeviceListValidity()
  • Evitez tous les appels récurrents aux fonction get_***
  • Utilisez les callbacks de changement de configuration:
    sensor.registerConfigChangeCallback()
  • Utilisez une connection réseau de type WebSocket:
    YAPI.RegisterHub("ws://...")


Pour une lecture de capteurs à fréquence maximale:

  • Relisez l'article sur la lecture par callback
  • Utilisez une lecture par callback périodique:
    sensor.registerTimedReportCallback()
  • Désactivez l'envoi des valeurs instantanées:
    sensor.muteValueCallbacks()
  • Allongez la durée de validité de l'inventaire des modules:
    YAPI.SetDeviceListValidity()
  • Evitez tous les appels récurrents aux fonctions get_***
  • Méfiez-vous des mini-PC ARM bon marché, le controlleur USB est parfois limité

En cas d'utilisation réseau,

  • Utilisez les callbacks de changement de configuration:
    sensor.registerConfigChangeCallback()
  • Utilisez une connexion de type WebSocket:
    YAPI.RegisterHub("ws://...")


Quoi qu'il en soit, n'oubliez pas que vous ne pourrez pas dépasser les limites imposées par la technologie des capteurs. Pour chaque module, une fréquence maximale de rafraîchissement est documentée, qui dépend principalement du circuit effectuant la mesure. Rien ne sert de transférer des mesures de lumières 100 fois par seconde si le capteur ne met à jour la mesure que dix fois par seconde...

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.