Cette semaine, dans le cadre de notre série à l'intention des débutants, nous allons aborder la structure logique des modules Yoctopuce et les diverses façons d'y accéder. Si vous êtes un de ces débutants, on vous suggère de lire attentivement cet article, même s'il vous parait un peu rebutant, il vous aidera à tirer le meilleur parti de vos modules Yoctopuce.
Du point de vue de l'API Yoctopuce, tous les modules ont une structure similaire. Une fois que vous aurez compris le principe, vous serez capable de faire fonctionner n'importe lequel d'entre eux.
Un module = un ensemble de fonctionnalité
Dans le monde Yoctopuce, chaque module Yoctopuce est présenté comme un ensemble de fonctionnalités. Par exemple un Yocto-Meteo mets à disposition trois fonctionnalités principales:
- Humidity qui permet de travailler avec le taux d'humidité mesurée par le module.
- Pressure qui permet de travailler avec la pression atmosphérique
- Temperature qui permet de travailler avec la température
Autre exemple: un Yocto-Thermocouple mets lui aussi à disposition la fonctionnalité Temperature qui est, du point de vue de l'API, équivalente à celle du Yocto-Meteo.
En plus des fonctionnalité principales, directement liées à la nature du module, chaque module peut proposer des fonctionnalités supplémentaires
- Module : La fonctionnalité "module" est présente sur tous les modules et permet de gérer le module en tant que tel. Elle permet par exemple de régler la luminosité des LED de signalisation, de gérer la yocto-balise etc....
- Datalogger : Tous les senseurs Yoctopuce ont une fonctionnalité "datalogger" qui permet d'enregistrer l'historique des mesures dans la mémoire flash du module.
Sauf cas exceptionnel, toutes les fonctionnalités sont indépendantes du point de vue de l'API, au point que vous pouvez travailler avec une fonctionnalité sans même savoir sur quel module elle se trouve.
Vous pouvez connaître la liste des fonctionnalités disponibles sur un module grâce au VirtualHub: la fenêtre de configuration de chaque module liste les fonctionnalités présentes:
Liste de fonctionnalités d'un Yocto-Meteo, sauf module qui est implicite
Programmation: Les classes
L'API Yoctopuce est répartie en différentes classes qui correspondent aux fonctionnalités des modules. Ainsi si vous avez besoin de travailler avec la température du Yocto-Meteo, vous aurez besoin de la classe YTemperature. Si vous désirez travailler avec la pression atmosphérique, vous aurez besoin de YPressure etc. Chacune de ces classes est définie dans un fichier distinct qui porte le même nom, par exemple en python YTemperature est définie dans ytemperature.py. Vous trouverez la doc complète de toutes les classes disponibles ici, y compris une version HTML interactive pour chaque langage de programmation.
Les classes un peu spéciales comme YModule et YAPI sont définies dans le fichier principal yocto_api, que vous devez toujours inclure, ce qui fait qu'elles sont toujours accessibles.
Passons à un exemple pratique: Imaginons que vous souhaitiez travailler avec un Yocto-Meteo en python et vous êtes intéressé à travailler avec la température et le taux d'humidité. Votre programme va commencer par:
from yocto_temperature import *
from yocto_humidity import *
Bien que la fonctionnalité Pressure soit présente sur le Yocto-Meteo, vous n'avez pas besoin d'inclure yocto_pressure si cette fonctionnalité ne vous intéresse pas.
Initialisation de l'API
Petit aparté indispensable: dans un programme qui gère des modules Yoctopuce, avant de commencer à faire quoi que ce soit, vous devez initialiser l'API Yoctopuce, ce qui se fait avec la fonction RegisterHub. Par exemple en C# vous devez faire quelques chose comme:
{ Console.WriteLine("Erreur RegisterHub : " + errmsg);
Environment.Exit(0);
}
A la place du paramètre "usb" vous pouvez aussi utiliser une adresse IP pour accéder à des modules Yoctopuce par réseau. Vous trouverez des explications détaillées sur les mille et un usage de RegisterHub dans cet article.
Programmation: énumération des fonctionnalités
L'API permet de lister facilement toutes les fonctionnalités du même type qui sont disponibles à travers tous les modules connectés. Par exemple le bout de code suivant vous permet de lister toutes les fonctionnalités de type Temperature:
while (t!=null)
{ Console.WriteLine(t.get_friendyName());
t = t.nextTemperature();
}
Si vous savez que dans votre projet il n'y a qu'une seule sonde de température, vous pouvez utiliser le code suivant pour retrouver votre sonde et sa valeur:
if (t==null) Console.WriteLine("pas de sonde de température disponible");
else Console.WriteLine(t.get_currentValue());
Ce code a un effet de bord intéressant: si vous remplacez votre module par un autre qui dispose aussi d'une sonde de température, votre programme continuera de marcher même s'il ne s'agit pas du même modèle. Par exemple, vous pouvez remplacer un Yocto-Temperature par un Yocto-Meteo, et votre code fonctionnera de la même manière sans même devoir être recompilé.
Attention cependant, lors d'une énumération, vous n'avez aucune garantie sur l'ordre dans lequel les fonctionnalités vous seront retournées. Si vous avez plusieurs fonctionnalités de même type dans votre système, vous risquez d'avoir un problème...
Programmation: accès direct par nom
En effet, les choses peuvent compliquer un peu dès lors qu'on a plusieurs modules connectés en même temps, surtout s'ils sont du même modèle. C'est pourquoi on peut aussi travailler par nom: vous avez à votre disposition un système d'identifiants matériels et un système de noms logiques:
Les identifiants matériels
Les identifiants matériels des différentes fonctionnalités sont assignés à la fabrication du module et ne peuvent pas être changés. Il sont sous la forme NuméroSerie.Nomfonction. Par exemple dans le cas du Yocto-Meteo, en supposant que le numéro de série du module soit: METEOMK1-12345 les identifiants matériels des différentes fonctionnalités seront:
- METEOMK1-12345.module pour le module
- METEOMK1-12345.temperature pour la température
- METEOMK1-12345.pressure pour la pression
- METEOMK1-12345.humidity pour l'humidité
- METEOMK1-12345.datalogger pour l'enregistreur de données
Attention, certains modules mettent à disposition la même fonctionnalité en plusieurs exemplaires. Dans ce cas les fonctionnalités sont numérotées. Par exemple dans le cas d'un Yocto-Thermocouple dont le numéro de série serait "THRMCPL1-12345" on aurait:
- THRMCPL1-12345.module pour le module
- THRMCPL1-12345.temperature1 pour la température du canal 1
- THRMCPL1-12345.temperature2 pour la température du canal 2
- METEOMK1-12345.datalogger pour l'enregistreur de données
Si vous connaissez l'identifiant matériel de votre fonctionnalité, il devient très facile d'y accéder directement. Imaginons que vous souhaitiez connaître la température mesurée par notre Yocto-Meteo dont le numéro de série est METEOMK1-12345, on écrirait:
if (t.isOnline()) Console.WriteLine(t.get_currentValue());
else Console.WriteLine("pas disponible");
Attention, YTemperature.FindTemperature reverra un objet valide même si la fonction n'a pas été trouvée. Pour savoir si la fonction est vraiment disponible, c'est à dire si le module correspondant est vraiment connecté, il vous faut utiliser isOnline() comme dans le bout de code précédent.
Vous pouvez trouver le numéro de série d'un module grâce au VirtualHub. Il est aussi imprimé sur l'emballage de chaque module.
Les noms logiques
Les identifiants matériels sont très pratiques pour accéder directement aux fonctions disponibles. Cependant, ils posent rapidement des problèmes si on commence à construire plusieurs exemplaires du même système: par définition les numéros de série des modules vont différer d'un système à l'autre. Ce qui rend difficile l'écriture d'un programme capable de gérer indifféremment chaque système. C'est pourquoi on peut aussi utiliser des noms logiques.
Vous pouvez attribuer à chaque fonctionnalité un nom logique arbitraire et utiliser ce nom logique en lieu et place de l'identifiant matériel. Les noms logiques sont persistants: une fois enregistrés, ils seront conservés dans le module même après une coupure de l'alimentation du dit module. Le moyen le plus simple pour configurer le nom logique d'une fonction consiste utiliser le VirtualHub. Par exemple, sur la capture d'écran ci-dessous on a renommé la fonctionnalité "temperature1" du module THRMCPL1-6C801 en CHAUDIERE
Affectation de noms logiques dans le VirtualHub
On peut maintenant utiliser le code suivant:
if (t.isOnline()) Console.WriteLine(t.get_currentValue());
else Console.WriteLine("pas disponible");
Ainsi vous pouvez construire plusieurs systèmes de surveillance de chaudière sans avoir à écrire du code spécifique à chaque installation. Il suffit de configurer le nom logique des diverses fonctions pendant qu'on construit le système et le tour est joué. Évidement, il est préférable qu'un nom logique soit unique au sein du même système.
Conclusion
Voila, vous connaissez l'essentiel de ce qu'il faut savoir sur la manière d'accéder depuis un programme aux diverses fonctionnalités d'un module Yoctopuce. Ceci dit, la structure logique des modules Yoctopuce et les classes qui leur sont associées comprennent d'autre subtilités dont vous trouverez le détail dans la doc des modules en question.