par , 21/08/2015 à 03h19 (8723 Affichages)
Étant donné que Gluon distribue désormais les runtimes JavaFX pour plateformes Linux ARM, je vais vous écrire un billet indiquant comment installer et préparer votre Raspberry Pi et comment y lancer une application JavaFX (ou une application en ligne de commande Java SE). Il s'agit d'un condensé et d'une remise au goût du jour des informations que j'avais écrites dans la FAQ JavaFX l'an dernier.
Prérequis
Voici tout d'abord une liste de prérequis pour pouvoir utiliser Java et JavaFX sur Raspberry Pi. Il est possible que cela fonctionne sur d'autres types de micro-ordinateurs utilisant ce type d'architecture ARM (ex. : Beagle Board) et d'autres systèmes d'exploitation Linux que Raspbian, mais je ne l'ai pas testé. Il vous faut donc :
- Un Raspberry Pi B ou plus récent ;
- Son adaptateur secteur ;
- Une carte SD disposant de la dernière version de Raspbian.
- Une connexion réseau ;
- Un écran (si votre écran est tactile, vous pourrez utiliser les fonctions tactiles de JavaFX) avec un port HDMI ;
- Un câble HDMI pour connecter l’écran ;
- Une souris USB pour les premiers tests ;
- Un clavier USB pour les premiers tests ;
- Un terminal supportant SSH (Cygwin, PuTTY, bash, etc.) pour se connecter à votre Raspberry Pi depuis votre ordinateur principal ;
- Un terminal ou un outil de transfert de fichiers supportant SCP ou SFTP (Cygwin, PuTTY, bash, Filezilla etc.) pour transférer des fichiers sur votre Raspberry Pi depuis votre ordinateur ;
- Votre IDE et vos outils de développement Java et JavaFX habituels ainsi que les bibliothèques nécessaires pour le développement.
Raspbian
Commencez par formater votre carte SD avec l'un des outils suivants :
- Windows :
- Mac OS X :
- Linux : utilisez gparted (outil graphique) ou parted (outil en ligne de commande) et reformatez votre carte SD en système de fichier FAT.
Vous pouvez ensuite utiliser l'outil NOOBS (New Out Of the Box Software) de Raspbian. Une fois l'archive téléchargée, il vous suffit de dézipper son contenu sur la racine de la carte mémoire. Insérez ensuite cette dernière dans votre Raspberry Pi et démarrez-le en connectant l'adaptateur secteur. Pensez à connecter et à allumer votre écran avant de démarrer le Raspberry Pi, sinon ce dernier utilisera la sortie composite au lieu de la sortie HDMI. En cas de soucis, il vous suffit de débrancher et de rebrancher l'adaptateur secteur pour que le Raspberry Pi redémarre.
Suivez ensuite la procédure d'installation en choisissant Raspbian comme système d'exploitation. Si jamais vous faites des fausses manipulations au cours de l'installation, il vous suffira d'effacer la carte SD à nouveau et de remettre NOOBS dessus avant de recommencer le processus. Si le processus d'installation vous le propose, pensez à activer un serveur SSH qui vous permettra de vous connecter à distance sur le micro-PC depuis votre ordinateur principal. JavaFX lance ses applications graphiques via le famebuffer, donc vous n'avez pas besoin de démarrer X à la fin de l'installation.
Comme indiqué sur la page de NOOBS, les identifiants par défaut sont :
- Identifiant : pi
- Mot de passe : raspberry
Vous utiliserez ces identifiants pour vous connecter sur la console ou pour vos sessions via SSH. Libre à vous de changer le mot de passe ou de créer d'autres comptes d'utilisateurs après coup. Dans le reste du billet, nous supposerons que vous utiliserez le compte pi par défaut.
N’hésitez pas à installer des logiciels et outils supplémentaires pour faciliter l'usage du Raspberry Pi si nécessaire :
1 2 3
| $ sudo apt-get install vi
$ sudo apt-get install emacs
$ sudo apt-get install gpm |
L'outil gpm permet de disposer du support de la souris en mode console, ce qui permet de sélectionner / copier / coller du texte plus facilement.
Pensez également à mettre à jour votre installation de Raspbian si besoin :
1 2
| $ sudo apt-get update
$ sudo apt-get upgrade |
JDK
Commencez par aller sur la page des téléchargements Java chez Oracle et récupérez la dernière version du JDK pour architecture Linux ARM v6/v7 Hard Float ABI pour ARM 32bit (actuellement : jdk-8u60-linux-arm32-vfp-hflt.gz). Transférez ensuite ce fichier sur votre Raspberry Pi en utilisant SCP ou SFTP. Ouvrez une session directement sur le Raspberry Pi ou connectez-vous à distance via SSH et effectuez les commandes suivantes :
1 2 3 4 5 6
| $ cd /opt
$ sudo mkdir java
$ cd java
$ sudo tar zxvf ~pi/jdk-8u60-linux-arm32-vfp-hflt.gz
$ sudo ln -s ./jdk1.8.0_60/ jdk
$ sudo ln -s ./jdk/jre/ jre |
Éditez maintenant le fichier ~pi/.profile dans un éditeur de texte que vous aurez installé au préalable (vi, emacs, etc.) et rajoutez les lignes suivantes en fin de fichier :
1 2
| export JAVA_HOME=/opt/java/jdk
export PATH=$JAVA_HOME/bin:$PATH |
Cela vous évitera d'utiliser la version de Java déjà installée par Rapsbian qui a souvent un cran de retard. Fermez et rouvrez ensuite votre session sur le Raspberry Pi et vérifiez que vous pouvez invoquer correctement la bonne version de l’interpréteur Java depuis la ligne de commande, ce qui devrait vous imprimer quelque chose comme :
1 2 3 4 5 6
| $ which java
/opt/java/jdk/bin/java
$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) Client VM (build 25.60-b23, mixed mode) |
Runtimes JavaFX
Allez ensuite sur la page des téléchargements de JavaFXPorts chez Gluon et récupérez le SDK de JavaFX pour Embedded (actuellement : armv6hf-sdk.zip). Transférez ensuite ce fichier sur votre Raspberry Pi en utilisant SCP ou SFTP. Faites ensuite :
Ce qui dézippera un répertoire nommé armv6hf-sdk dans votre home directory (/home/pi/ si vous utilisez l'utilisateur par défaut).
Configuration du framebuffer
Vous devez ensuite configurer correctement les dimensions du framebuffer. Éditez le fichier /boot/config.txt avec un éditeur de texte (vi, emacs, etc.) et modifiez les lignes suivantes pour vous caler sur la résolution native de votre écran :
1 2
| framebuffer_width=1280
framebuffer_height=720 |
Par exemple, l’écran que j'utilise pour mes tests a une résolution de 1920 x 1080. Si je ne modifie pas les valeurs incluses dans ce fichier, l'affichage graphique ne couvrira pas toute la surface de l’écran. Évidemment, afficher une résolution plus élevée demandera plus de mémoire et plus d'effort au CPU du Raspberry Pi.
Développement de l'application
Commencez à développer votre application sur votre ordinateur principal comme à l'ordinaire avec votre IDE favori. Je vous conseille de ne pas inclure d'espace dans le nom du projet pour permettre à l’exécution à distance de fonctionner correctement (voir plus bas). De manière générale, votre ordinateur étant plus performant et disposant de bien plus de mémoire que le Pi, c'est sur votre ordinateur principal que vous développerez et testerez l'application, en utilisant votre IDE habituel. Vous devrez cependant penser à inclure toutes les bibliothèques tierces que vous comptez utiliser sur le Pi dans votre espace de développement.
Si jamais vous devez utiliser des bibliothèques natives pour, par exemple, exploiter les périphériques du Raspberry Pi, il vous faudra vous reposer sur l’exécution à distance pour tester le fonctionnement de votre programme.
Exécution à distance
De manière générale, vous allez tester votre application en long et en large sur votre ordinateur de manière à être sûr qu'elle fonctionne correctement avant de la transférer sur le PI. Cependant, NetBeans (et probablement les autres IDE) dispose d'un mode fort utile qui permet d’exécuter une application sur une JVM distante (ici, sur le Pi). Cela permet de tester l'affichage directement sur la machine cible, et de s’apercevoir de la différence de performance ou de comportement d'entre votre ordinateur et votre Pi, et également de tester directement l’accès aux périphériques et port du micro-ordinateur.
Allez dans le menu Tools -> Java Platforms, puis cliquez sur Add Platform....
Choisissez ensuite Remote Java Standard Edition et cliquez sur Next >.
Donnez maintenant un nom à votre plateforme distante et renseignez le nom de la machine dans le champ Host.
Saisissez également votre nom d'utilisateur et votre mot de passe dans les champs appropriés en vous assurant que l'option Use Password Authentication est sélectionnée.
Dans le champ Remote JRE Path, saisissez l'emplacement d'installation du JRE sur le Raspberry Pi.
Et finissez en indiquant un répertoire de travail dans lequel NetBeans copiera vos projets (évitez les espaces dans les noms).
NetBeans effectua des tests pour vérifier si votre JVM est valide lorsque vous cliquerez sur Finish ; si vous avez renseigné correctement tous les champs, ce test devrait se conclure sans rencontrer de problème.
Vous pouvez à tout moment modifier les valeurs des champs et relancer le test de cette nouvelle plateforme Java distante.
Éditez maintenant la configuration de votre projet et allez dans le menu Run.
Créez une nouvelle configuration et dans la boite déroulante, Runtime Plaform, sélectionnez votre nouvelle JVM distante.
Pour une application JavaFX, vous devez rajouter -Djava.ext.dirs=/home/pi/armv6hf-sdk/rt/lib/ext/ dans le champ VM Options.
Ce paramètre rajoutera le SDK de JavaFX pour ARM dans les extensions du JDK, ce qui permettra de lancer votre application JavaFX.
Maintenant, lancez votre application. S'il agit d'une application graphique, au bout d'un certain temps (10*s - 1*min), l'affichage textuel de la console sera remplacé par l'affichage graphique de votre application. L'application peut mettre du temps à s'afficher en fonction de la complexité de votre UI et compte tenu des faibles performances du Raspberry Pi. Si votre application affiche des messages sur la console, ces derniers seront affichés dans la console des sorties de l'application dans NetBeans sur votre ordinateur.
Ma première application JavaFX sur le PI, l'application par défaut créée par NetBeans lorsqu’on initialise un nouveau projet JavaFX.
J'ai oublié de redimensionner le
Stage pour qu'il fasse toute la taille du
Screen...
Bogue : il y a un bogue de gestion de la souris dans les runtimes distribués par Gluon et JavaFXPorts. Au lancement de votre application, la console va afficher plusieurs lignes dans le style :
1 2 3 4 5 6 7 8 9 10 11 12
| Udev: Failed to write to /sys/class/input/mice/uevent
Check that you have permission to access input devices
Udev: Failed to write to /sys/class/input/event0/uevent
Check that you have permission to access input devices
Udev: Failed to write to /sys/class/input/event1/uevent
Check that you have permission to access input devices
Udev: Failed to write to /sys/class/input/input0/uevent
Check that you have permission to access input devices
Udev: Failed to write to /sys/class/input/input1/uevent
Check that you have permission to access input devices
Udev: Failed to write to /sys/class/input/mouse0/uevent
Check that you have permission to access input devices |
De plus, le curseur de la souris ne sera pas présent dans votre application et il n'y aura aucune réaction aux clics.
Pas de panique ! tout ce que vous avez à faire en attendant un correctif des runtimes, c'est de débrancher le connecteur de la souris et de le rebrancher dans le port USB. Le curseur apparaitra alors dans votre application et vous pourrez l'utiliser comme d'habitude. Ce problème n'est pas lié à la présence de gpm.
Débogage à distance
En théorie, cette fonctionnalité devrait permettre également le débogage à distance, mais cela ne fonctionne pas pour moi. Il faudra donc se contenter de déboguer l'application en utilisant des affichages console ou des logs.
Considérations et Performances
Vous devez bien garder quelques points en tête lors du développement de votre application.
Le Raspberry Pi, n'est pas un foudre de guerre : une opération normale sur votre ordinateur s’exécutera plutôt lentement sur le Pi. Une opération déjà longue sur votre ordinateur s’exécutera trèèèèèèèèèèèèèès lentement sur le Pi. Un Raspberry Pi 2 s’avérera sans doute bien plus véloce qu'un modèle B ou B+, mais il restera globalement plus lent que le CPU de votre ordinateur principal.
Vous avez accès à beaucoup beaucoup moins de mémoire que sur votre ordinateur principal. En fait, sur les modèles de plateformes ARM les plus anciennes, vous êtes bien plus proches d'une plateforme capable de supporter JavaME (téléphone, smartphone) que d'une plateforme capable de supporter JavaSE. Donc, essayez d’être économe sur vos allocations d'objets pour des raisons de performances sur l'allocation elle-même et, bien sûr, pour la consommation mémoire de votre application. N'oubliez pas non plus que le ramasse-miette est une opération coûteuse qui ralentira probablement votre application sur cette plateforme s'il s'effectue trop souvent.
Côté graphismes, le framebuffer ne dispose pas d'un système de fenêtrage, donc vous n'aurez pas accès à des fenêtres décorées. Votre affichage sera donc de taille fixe la plupart du temps : votre stage devra s'adapter aux dimensions du framebuffer qu'il peut récupérer à travers la classe javafx.stage.Screen.
Pour la même raison, pensez à inclure dans votre UI un bouton qui permet de quitter le programme durant sa phase de développement. En effet, la surface graphique sur laquelle vous serez amené à afficher votre UI n'en aura pas puisqu'elle n'est pas décorée comme une fenêtre classique d'un système de fenêtrage. Si vous avez oublié d'en mettre un, vous pouvez ouvrir une session via SSH sur le PI, vous identifier et rechercher puis terminer le processus Java, ce qui arrêtera le programme. Vous pouvez également redémarrer le Raspberry Pi en débranchant puis rebranchant son adaptateur secteur.
Vous pouvez également définir la variable suivante dans votre fichier .profile :
Cela vous permettra alors d'utiliser la combinaison de touches Control C pour forcer votre application à se terminer. Cette astuce est bien sûr uniquement utile en développement et doit être désactivée lorsque vous passez votre application kiosque en production.
Si vous utilisez un écran tactile, le wiki de l'OpenJFX vous indiquera la démarche à suivre pour la calibration de l’écran.
Plusieurs fonctionnalités de JavaFX ne sont pas disponibles, fonctionnent mal ou ne fonctionnent pas du tout sur ces plateformes, cela inclut :
- WebView et tout le support du HTML 5 ;
- Le support des médias ;
- Le support de la 3D.
Lorsque vous essayez de customiser votre UI, essayer de conserver des règles CSS assez simples ; le parsing et l'application de règles CSS trop complexes étant très gourmands en mémoire et en temps CPU. De manière générale, évitez les constructions SceneGraph trop complexes et préférez les couleurs opaques aux couleurs translucides ou transparentes pour disposer d'une bonne performance graphique. Tout comme sur plateformes mobiles, vous obtiendrez de meilleures performances en utilisant des bitmap (9-slicing, skinning, etc.) pour décorer vos composants plutôt qu'en utilisant les règles habituelles de redéfinition des bordures et couleurs de fond des Region. Vous pouvez retrouver ces astuces dans la présentation de la session "JavaFX Graphics Tips and Tricks" par Richard Bair lors de la JavaOne 2012.
Veuillez noter toutefois que la VRAM est disponible en quantité limitée sur le périphérique et donc que vous risquez de tomber à court de mémoire vidéo si vous utilisez des images trop grosses ou en trop grand nombre. Sur des versions anciennes de Rasbian, il peut être nécessaire d'invoquer l'utilitaire raspi_config pour modifier la quantité de mémoire partagée disponible en tant que mémoire vidéo. Les versions les plus récentes de l'OS peuvent modifier cette répartition de manière dynamique.
Lancement de l'application
Maintenant que vous avez développé et débogué votre application, et que vous êtes sûr qu'elle fonctionne correctement packagez-la dans un fichier JAR et transférez ces fichiers sur votre Raspberry Pi. Par exemple, si votre projet est sous NetBeans, il faut transférer tout le contenu du répertoire dist de votre projet.
Connectez-vous ensuite sur votre Raspberry Pi, et déplacez-vous dans le répertoire dans lequel vous avez transféré les fichiers et faites :
$ java -Djava.ext.dirs=/home/pi/armv6hf-sdk/rt/lib/ext/ -cp lib/ -jar monFichier.jar
Vous pouvez également vous créer un script pour vous permettra de lancer l'application sans avoir à retaper la ligne de commande à chaque fois.
Note : même si ce n'est pas vraiment recommandé, pour pallier le problème de la souris, vous pouvez également lancer l'application en tant que root.