Il y a encore peu de temps, vouloir tracer un graphe dynamique des valeurs d'un capteur Yoctopuce demandait d'utiliser une base de données pour stocker l'historique. En effet, récupérer les données du datalogger était clairement trop lent pour une application interactive. Il se trouve que la partie datalogger des produits Yoctopuce a été considérablement améliorée tant au niveau de l'API qu'au niveau des firmwares. Récupérer les données du datalogger se fait maintenant en un clin d’œil. Démonstration avec un exemple en C#.
Pour vous montrer à quel point le datalogger est devenu agréable à utiliser, on va écrire ensemble une petite application C# qui trace l'historique des données d'un capteur Yoctopuce, puis met à jour le graphe en temps réel. C'est une application assez intéressante car elle tire parti d'un certain nombre de fonctionnalités apparues avec la nouvelle API.
La classe YSensor
Ysensor est une nouvelle classe, parente de tous les capteurs Yoctopuce. Plus besoin d'écrire du code spécifique à chaque capteur: on peut se contenter de code générique pour autant qu'on se limite aux fonctions de base communes à tous les capteurs, comme get_currentValue, get_unit etc..
loadMore
Le chargement des données du datalogger se fait de manière itérative grâce à loadMore qui renvoie le pourcentage de données effectivement chargées et permet ainsi d'afficher un belle barre de progression pendant le chargement des données.
Les Timed Report
Il y a maintenant un nouveau type de callback: les TimedReport. Une fois défini, ce callback appelle à intervalle régulier une fonction de votre choix avec la valeur du capteur qui vous intéresse.Très pratique pour mettre à jour le graphe automatiquement.
Il se trouve que framework .NET met à disposition une classe Chart, qui permet de tracer relativement facilement des graphes tout à fait corrects, avec gestion de zoom et tout et tout. Il n'y a donc qu'à sortir les données du datalogger pour les transmettre à l'objet .NET. Voyons de plus près comment s'y prendre.
Inventaire dynamique des capteurs
On va vouloir que notre application permette de choisir entre tous les capteurs connectés. Pour ça, il va falloir construire un inventaire des capteurs que l'on pourra présenter à l'utilisateur sous la forme d'un comboBox. Évidement, on aimerait que ce comboBox soit mis à jour au fur et à mesure que l'on connecte ou déconnecte des capteurs. L'USB étant plug-and-play, autant en profiter :-)
Pour faire ça, on installe deux callbacks: un qui sera appelé lorsqu'un module est connecté, l'autre qui sera appelé dès qu'un module est débranché.
YAPI.RegisterDeviceRemovalCallback(deviceRemoval);
Notez que ces callbacks ne sont en fait appelés que pendant l'exécution de YAPI.UpdateDeviceList, il faudra donc appeler cette fonction de temps en temps, à l'aide d'un timer par exemple.
A chaque fois que deviceArrival est appelé, on fait une énumération de tous les capteurs connectés, et on rajoute ceux qui manquent dans le comboBox.
{ YSensor s = YSensor.FirstSensor();
while (s != null)
{ if (!comboBox1.Items.Contains(s))
comboBox1.Items.Add(s);
s = s.nextSensor();
}
}
A chaque fois que deviceRemoval est appelé, on vérifie que chaque capteur stocké dans le comboBox est bien onLine, dans le cas contraire on le supprime de la liste.
{ for (int i = comboBox1.Items.Count - 1; i >= 0; i--)
if (!((YSensor)comboBox1.Items[i]).isOnline())
comboBox1.Items.RemoveAt(i);
}
Voilà pour l'inventaire dynamique.
Extraction des données du datalogger
L'extraction des données de se fait en trois temps:
- On demande à l'API de charger les données du datalogger. Pour cela,on utilise la fonction loadMore du DataSet renvoyé par la fonction get_recordedData du capteur. On appelle cette fonction loadMore en boucle, qui renvoie très obligeamment le pourcentage de données déjà chargées, ce qui permet de mettre à jour une barre de progression.
- A ce moment, toutes les données du datalogger ont été transférées du module vers l'ordinateur, mais elles se trouvent encore quelque part dans les bas fonds de l'API. On utilise alors la fonction get_measures() pour les transférer dans une liste C#.
- Finalement, il ne reste plus qu'à transmettre ces données au graphe.
YDataSet data = s.get_recordedData(0, 0);
// chargement de données
int progress = data.loadMore();
while (progress < 100)
{ progressBar.Value = progress;
Application.DoEvents();
progress = data.loadMore();
}
// transfert dans un tableau
List<YMeasure> alldata = data.get_measures();
// envoi des données au graphe
for (int i = 0; i < alldata.Count; i++)
{ DateTime t = UnixTimeStampToDateTime(alldata[i].get_endTimeUTC())
chart1.Series[0].Points.AddXY( t, alldata[i].get_averageValue());
}
// affichage des unités
chart1.ChartAreas[0].AxisY.Title = s.get_unit();
Mise à jour en temps réel
Pour mettre le graphe à jour en temps réel, on va utiliser le tout nouveau callback TimedReport. Ce callback, configurable indépendamment pour chaque capteur, permet d'appeler la fonction de votre choix avec la valeur du capteur.
s.set_reportFrequency("3/s"); // 3 fois par seconde
s.registerTimedReportCallback(newSensorValue);
Attention, le callback TimedReport n'est appelé que pendant l'exécution de YAPI.Sleep ou YAPI.HandleEvents, il faudra donc appeler l'une ou l'autre de ces fonctions de temps en temps. Un timer est idéal pour cela.
Le callback, quant à lui, est des plus simple: il se contente d'ajouter au graphe la mesure reçue en paramètre.
{ DateTime t = UnixTimeStampToDateTime(m.get_endTimeUTC());
chart1.Series[0].Points.AddXY(t , m.get_averageValue());
}
Et voilà, on a fait le tour du code Yoctopuce qui permet de tracer un graphe de l'historique d'un capteur grâce aux données du datalogger, et de garder ce graphe constamment à jour. Le projet complet est disponible ici, il sera intégré aux exemples de la librairie C# dès la prochaine release.
Une application de traçage de graphe, écrite en deux temps, trois mouvements
Bien entendu, pour que cette application fonctionne vous aurez besoin d'une librairie Yoctopuce et de firmwares à jour. Ils sont encore en beta-test mais peuvent être téléchargés ici.