Il y a quelques jours, un de nos clients nous a fait remarquer que notre libraire C++ ne compilait pas avec Qt / MinGW sous Windows (OSX et Linux n'étaient pas affectés). Nous avons publié le fix sur GitHub, mais nous avons réalisé que nous n'avions jamais parlé de Qt sur notre site. Il est temps d'y remédier... Qt est un environnement de programmation graphique multi-plateforme, qui permet de générer des exécutables pour chaque OS. Nous allons donc créer un petit programme qui liste les modules Yoctopuce connectés, et grâce au framework Qt le même projet pourra être utilisé pour créer un exécutable Windows, Linux et Mac OS.
Pour être francs, nous n'avions jamais utilisé Qt avant cette semaine... Nous avons été surpris par la relative facilité d'utilisation du framework. L'installation de Qt se fait en quelques clics. Le framework propose son propre IDE, et avec très peu de code on arrive à écrire une application qui fonctionne sur tous les OS majeurs. Nous n'allons pas écrire un cours sur Qt mais juste décrire les paramètres à modifier pour pouvoir utiliser la libraire Yoctopuce C++ dans une application Qt.
L'IDE de Qt : Qt Creator
Ajouter la librairie C++
Avant de pouvoir utiliser la librairie Yoctopuce il faut modifier votre projet pour ajouter les fichiers sources de la librairie Yoctopuce et les quelques librairies système nécessaires. Vous pouvez soit utiliser la fonction "Add Existing Files..." ou directement modifier votre fichier .pro pour rajouter les fichiers aux variables SOURCES et HEADER. Il faut aussi mettre à jour l'INCLUDEPATH pour que le compilateur trouve les fichiers .h.
SOURCES += ../../../Sources/yocto_api.cpp \
../../../Sources/yapi/ythread.c \
../../../Sources/yapi/ytcp.c \
../../../Sources/yapi/ystream.c \
../../../Sources/yapi/yprog.c \
../../../Sources/yapi/ypkt_win.c \
../../../Sources/yapi/ypkt_osx.c \
../../../Sources/yapi/ypkt_lin.c \
../../../Sources/yapi/ymemory.c \
../../../Sources/yapi/ykey.c \
../../../Sources/yapi/yjson.c \
../../../Sources/yapi/yhash.c \
../../../Sources/yapi/yfifo.c \
../../../Sources/yapi/yapi.c
# add Yoctopuce Header files
HEADERS += ../../../Sources/yocto_api.h \
../../../Sources/yapi/yversion.h \
../../../Sources/yapi/ythread.h \
../../../Sources/yapi/ytcp.h \
../../../Sources/yapi/yproto.h \
../../../Sources/yapi/yprog.h \
../../../Sources/yapi/ymemory.h \
../../../Sources/yapi/ykey.h \
../../../Sources/yapi/yjson.h \
../../../Sources/yapi/yhash.h \
../../../Sources/yapi/yfifo.h \
../../../Sources/yapi/ydef.h \
../../../Sources/yapi/yapi.h
# add Yoctopuce Library to the Include path
INCLUDEPATH += $$PWD/../../../Sources/
Si vous lancez votre projet avec ces modifications, la compilation va passer mais le linker va refuser de créer l'exécutable. Il faut ajouter au projet quelques libraires système nécessaires à la librairie Yoctopuce. Cependant ces librairie sont spécifiques à chaque OS: Pour Windows nous avons besoin d'ajouter la librairie Windows Sockets 2 (ws2_32.lib) et la librairie Setup API (SetupApi.lib), pour Linux nous avons besoin de la libUSB 1.0 (libusb-1.0.a), enfin pour OS X nous avons besoin des frameworks CoreFoundation et IOKit. Pour vous simplifier la vie voici les quelques lignes à ajouter dans votre fichier .pro pour que le projet compile.
macx: LIBS += -framework CoreFoundation
macx: LIBS += -framework IOKit
# add windows socket 2 library and Setup API
win32: LIBS += -lws2_32
win32: LIBS += -lSetupApi
# add libusb 1.0
unix:!macx: LIBS += -lusb-1.0
Maintenant la librairie Yoctopuce est compilée et linkée à votre projet. Il ne reste plus qu'à l'utiliser.
Coder l'application
Il faut commencer par initialiser l'API Yoctopuce pour pouvoir accéder à tous les modules connectés sur le bus USB. Il suffit d'appeler la méthode YAPI::RegisterHub() en lui spécifiant que l'on veut accéder aux modules connectés par USB (avec le paramètre "usb").
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
string errmsg;
if (YAPI::RegisterHub("usb",errmsg)!= YAPI::SUCCESS){
qDebug("Unable to start Yoctopuce API");
qDebug(errmsg.c_str());
exit(1);
}
Inventory w;
w.show();
return a.exec();
}
La fenêtre principale de l'application ne contient qu'un QListWidget qui va afficher le numéro de série des modules connectés. les modules qui ont leur LED allumée seront affichés en bleu les autres seront affichés en noir. Ce widget sera rafraîchit chaque secondes par la méthode updateInventory() (en utilisant un QTimer qui va appeler la méthode). Cet méthode va forcer une énumération USB (avec YAPI::UpdateDeviceList()) et mettre à jour notre QListWidget avec les modules connectés.
{
string errmsg;
YAPI::UpdateDeviceList(errmsg);
ui->listWidget->clear();
YModule *module = YModule::FirstModule();
while(module){
QListWidgetItem *item =
new QListWidgetItem(QString(module->get_serialNumber().c_str()));
if(module->get_beacon() == YModule::BEACON_ON)
item->setTextColor(Qt::blue);
else
item->setTextColor(Qt::black);
ui->listWidget->addItem(item);
module = module->nextModule();
}
}
Le code complet est disponible dans le répertoire Examples/Prog-QT de notre librairie C++ (Note: pour l'instant uniquement disponible sous GitHub). Voilà les screenshots du même projet compilé et exécuté sur les trois OS:
Conclusion
Comme nous venons de le voir, il est très facile de créer trois exécutables depuis un seul projet Qt. Le framework est suffisamment souple et bien pensé pour que l'on puisse facilement utiliser notre librairie et accéder aux modules USB. Et quand un tel framework permet de générer une application graphique pour trois OS différents depuis un seul et même projet, c'est suffisamment rare pour être apprécié