Cette semaine, on se propose de vous montrer comme faire une application Windows qui utilise des modules Yoctopuce, en C#. L'exercice est intéressant parce que la plupart des exemples C# fournis avec l'API Yoctopuce sont en fait des applications consoles. Les applications Windows Forms introduisent quelques petites différences qui méritent d'être notées. Attention cet article n'a pas la prétention de vous apprendre à programmer en C#, vous êtes supposé avoir quelques notions :-)
On va écrire une petite application toute simple qui affiche la valeur d'un capteur de température. Puis on généralisera pour afficher la valeur de n'importe quel capteur.
Installation de l'API
La première chose à faire consiste à installer la librairie Yoctopuce pour C#. Elle peut être téléchargée depuis la page idoine. C'est un fichier Zip qu'il vous suffit de dé-zipper où bon vous semble. Le répertoire indispensable est "Sources" ainsi que son sous-répertoire "dll". Une fois les fichiers copiés, vous pouvez considérer l'installation comme terminée.
Avant d'aller plus loin, on vous suggère de lire avec attention, si ce n'est déjà fait, notre article sur la structure logique des modules Yoctopuce, cela vous aidera à bien comprendre la suite.
Pour illustrer cette article, on a utilisé VisualStudio 2015. Mais le principe reste tout à fait valable pour les autres versions.
L'application: mise en place
Après avoir ouvert VisualStudio, créez un nouveau projet C# de type Windows Forms. Vous allez vous retrouver avec une Form toute vide.
Créez un nouveau projet C# de type Windows Form
Il s'agit ensuite d'indiquer à VisualStudio qu'il doit utiliser l'API Yoctopuce. On va avoir besoin d'utiliser les fichiers yocto-api.cs, Yocto-temperature.cs ansi que yapi.dll. Faites un clic droit sur votre projet dans le "Solution Explorer", et choisissez: Add > Existing Item....
Add existing item
Choisissez les fichiers yocto-api.cs, Yocto-temperature.cs depuis l'endroit où vous avez dé-zippé l'API et choisissez le bouton "Add as link". Utiliser "Add as link" n'est pas anodin, cela permet d'utiliser les fichiers depuis leur endroit original plutôt que les copier dans votre projet. Ainsi, si vous mettez à jour les fichiers de votre API l'application sera automatiquement à jour à la compilation suivante. Mais si vous préférer les copier dans le répertoire de votre projet, on ne vous en voudra pas :-)
Recommencez l'opération avec le fichier yapi.dll qui se trouve dans le sous répertoire "dll". Attention vous aurez à changer le filtre des fichiers et choisir "Executable files (*.exe, *.dll, *.ocx)" au lieu de "Visual C# files (*.cs; *.resx ...)".
Ajouter yapi.dll
Un fois la DLL ajoutée, sélectionnez-la dans le Solution Explorer et changez sa propriété "Copy to Output Directory" à "Copy always". Cela aura pour effet de systématiquement copier la dll api.dll dans le répertoire de l'exécutable.
Copier la Dll
Voilà c'est prêt, on va pouvoir commencer à coder.
Initialisation de l'API
La première chose à faire consiste initialiser l'API à l'aide de YAPI.RegisterHub, le meilleur endroit pour faire ça est le fichier program.cs qui contient le point d'entrée de l'application. Ainsi, si l'initialisation de l'API Yoctopuce se passe mal on pourra tout de suite arrêter le lancement de l'application.
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string errsmg = "";
if (YAPI.RegisterHub("usb", ref errsmg) == YAPI.SUCCESS)
Application.Run(new Form1());
else
MessageBox.Show("Init error:" + errsmg);
}
L'interface utilisateur
Revenons à notre form toute vide, pour faire simple, on va insérer deux labels: Le premier pour indiquer la température. Le second pour indiquer le nom du capteur utilisé.
On ajoute deux labels
On initialise le texte des labels dans le constructeur de la Form
{
InitializeComponent();
label1.Text = "N/A";
label2.Text = "No sensor detected";
}
Interface avec le capteur
Contrairement, à une application console, on ne va pas pouvoir se permette de créer une boucle sans fin pour lire le capteur en permanence. C'est pourquoi on va utiliser un timer qui va appeler une fonction à une fréquence de 10Hz. C'est cette fonction qui va se charger de:
- Appeler YAPI.HandleEvents assez régulièrement. En fait ce n'est pas 100% nécessaire dans notre cas, mais c'est une bonne pratique de donner le contrôle à l'API Yoctopuce de temps en temps.
- Appeler YAPI.UpdateDeviceList une fois toutes les deux secondes, ce qui forcera a l'API a re-détecter le branchement de nouveaux modules. C'est un processus assez lourd, il faut éviter de le faire trop souvent d'où les deux secondes entre chaque appel.
- Détecter la première fonctionnalité "YTemperature" disponible à l'aide de YTemperature.FirstTemperature()
- Si cette fonctionnalité est disponible, lire la température et mettre à jour l'interface.
Ce qui nous donne le code suivant:
int hardwaredetect = 0;
private void timer1_Tick(object sender, EventArgs e)
{
string errmsg ="";
if (hardwaredetect == 0) YAPI.UpdateDeviceList(ref errmsg);
hardwaredetect = (hardwaredetect + 1) % 20;
YAPI.HandleEvents(ref errmsg);
if (sensor == null) sensor = YTemperature.FirstTemperature();
if (sensor != null)
{
if (sensor.isOnline())
{
label1.Text = sensor.get_currentValue()+ sensor.get_unit();
label2.Text = sensor.get_friendlyName();
}
else
{
label1.Text = "OFFLINE";
label2.Text = "Sensor is offline";
sensor=null;
}
}
}
Comme chacun sait, l’utilisateur est un gros fourbe, il va sûrement nous débrancher le module en cours de route. C'est pourquoi, avant d'accéder à une fonctionnalité, on fait bien attention de vérifier que le module correspondant est connecté l'aide de l'appel sensor.isOnline(). Si on résume, le code complet du Form ressemble à ça:
{
public Form1()
{
InitializeComponent();
label1.Text = "N/A";
label2.Text = "No sensor detected";
timer1.Interval = 100;
timer1.Tick += timer1_Tick;
timer1.Enabled = true;
}
YTemperature sensor = null;
int hardwaredetect = 0;
private void timer1_Tick(object sender, EventArgs e)
{
string errmsg ="";
if (hardwaredetect == 0) YAPI.UpdateDeviceList(ref errmsg);
hardwaredetect = (hardwaredetect + 1) % 20;
YAPI.HandleEvents(ref errmsg);
if (sensor == null) sensor = YTemperature.FirstTemperature();
if (sensor != null)
{
if (sensor.isOnline())
{
label1.Text = sensor.get_currentValue()+ sensor.get_unit();
label2.Text = sensor.get_friendlyName();
}
else
{
label1.Text = "OFFLINE";
label2.Text = "Sensor is offline";
sensor=null;
}
}
}
}
Et une fois qu'on compile tout ça, on obtient le résultat attendu, une fenêtre Windows qui affirme la température dès qu'un capteur de température Yoctopuce est branché:
Ça marche!
Vous noterez que ce code, volontairement simpliste, n'est capable de ne gérer qu'un seul capteur de température à la fois. Si vous voulez gérer plusieurs senseurs, pas de problème, l'API est bien évidement prévue pour.
Tour de magie
Cet exemple ne gère que les capteurs de température, mais en changeant juste deux lignes, on peut le faire marcher avec n'importe quel senseur Yoctopuce: il suffit d'utiliser la classe YSensor à la place de la classe YTemperature:
YTemperature sensor = null;
....
if (sensor == null) sensor = YTemperature.FirstTemperature();
// par
YSensor sensor = null;
....
if (sensor == null) sensor = YSensor.FirstSensor();
Et hop, maintenant ça marche aussi avec un capteur de lumière.
Maintenant ça marche aussi avec les autres capteurs
Ce "tour de magie" marche grâce au fait que toutes les classes Yoctopuce correspondant à des fonctionnalités de type senseur héritent de la classe YSensor. Vous pouvez utiliser la classe YSensor pour accéder aux fonctions de base d'un senseur comme obtenir la valeur courant ou l'unité de mesure.
Voilà, voilà, on a vu l'essentiel, maintenant avec l'aide de la doc de référence, vous devriez être capables de voler de vos propres ailes.