Introduction
Dans la continuité de mon apprentissage, je me suis attaqué aux commandes et aux tâches cron. Du coup, je vous fais un petit tutoriel sur le sujet afin de vous expliquer ce que j’ai compris. Il se peut donc qu’il y est des erreurs et je vous invite à m’en faire part si vous en voyez.
Il est conseillé de lire le premier tutoriel si vous commencez dans le développement de plugin. Vous le trouverez ici et le code source final ici.
Mise en place de l’environnement
Je vous invite une fois de plus à installer Jeedom sur votre poste et ne pas faire vos essais sur votre installation domotique.
Si n’avez pas de plugin en cours de développement, vous pouvez récupérer celui du premier tutoriel en tapant la commande suivante dans votre répertoire /var/www/html/plugins/ :
1 2 |
git clone https://github.com/Sylvaner/JeedomPluginTutoriel1 mv JeedomPluginTutoriel1 tutoriel |
Ainsi l’ensemble des modifications se feront dans ce répertoire tutoriel. Pour la suite de ce tutoriel, l’identifiant du plugin sera donc tutoriel, vous devrez donc remplacer ce mot si vous avez donné un autre nom.
N’oubliez pas d’activer le plugin si vous voulez le voir apparaitre dans l’interface.
Du javascript dans votre plugin
Pour utiliser les commandes liées aux équipements, il faut passer par un fichier javascript qui va ajouter les lignes dynamiquement pour chaque commande dans le tableau.
Pour cela, il faut créer le fichier tutoriel.js dans le répertoire desktop/js et le charger en ajoutant dans votre fichier desktop/php/tutoriel.php :
1 |
include_file('desktop', 'tutoriel', 'js', 'tutoriel'); |
Pour rappel, les paramètres de la fonction include_file sont :
- Répertoire de base dans lequel se trouve le fichier,
- Nom du fichier,
- Type du fichier,
- Entité dans laquelle trouver ce fichier. Si ce paramètre n’est pas renseigné, ce seront les fichiers du core de Jeedom qui seront chargés.
Dans ce fichier javascript, nous allons rajouter une fonction :
1 2 3 4 |
function addCmdToTable(_cmd) { } |
Cette fonction sera appelée dans deux cas :
- Lorsque vous cliquez sur le bouton pour ajouter une commande,
- Lorsque vos équipements contiennent des commandes par défaut.
Elle possède un seul paramètre _cmd qui contient les données de la commande. C’est un objet JSON qui contient les options de la commande.
Lorsque nous créons une commande manuellement, elle ne fournit pas ce paramètre, il faut donc créer l’objet, pour cela nous ajoutons le code suivant :
1 2 3 4 5 6 7 8 |
function addCmdToTable(_cmd) { // Test si le paramètre a été défini if (!isset(_cmd)) { // Initialise _cmd _cmd = {configuration: {}}; } } |
Ainsi la variable _cmd sera un objet JSON contenant une clé configuration vide.
Cette commande va s’ajouter dans le tableau en dessous qui ne contient pour le moment que la colonne champ.
Nous allons donc ajouter une ligne à ce tableau en javascript :
1 2 3 4 5 6 7 8 |
var row = ' \ <tr> \ <td> \ <input class="cmdAttr form-control input-sm" data-l1key="id" style="display : none;"> \ <input class="cmdAttr form-control input-sm" data-l1key="name"> \ </td> \ </tr>'; $('#table_cmd tbody').append(row); |
Ainsi, on créé la ligne directement avec une chaîne de caractère et on l’insère dans la balise <tbody> qui représente le contenu du tableau.
Si on clique sur le bouton pour ajouter une commande, on voit les lignes se rajouter.
On remarque dans le code l’ajout d’un champ caché qui contiendra l’identifiant de la commande.
Ajouter des champs aux commandes
Avoir des noms aux commande, c’est bien, mais faire quelque chose avec, c’est mieux.
Nous allons donc ajouter quelques colonnes à notre tableau. Celui-ci est affiché à partir du fichier desktop/php/tutoriel.php. Actuellement nous avons ceci :
1 2 3 4 5 6 7 8 9 |
<table id="table_cmd" class="table table-bordered table-condensed"> <thead> <tr> <th style="width: 300px;">{{Nom}}</th> </tr> </thead> <tbody> </tbody> </table> |
Nous allons juste rajouter deux colonnes :
1 2 3 4 5 6 7 8 9 10 11 12 |
<table id="table_cmd" class="table table-bordered table-condensed"> <thead> <tr> <th style="width: 300px;">{{Nom}}</th> <th>{{Type}}</th> <th>{{Historique}}</th> <th>{{Actions}}</th> </tr> </thead> <tbody> </tbody> </table> |
Nous aurons donc un type pour chaque commande (info ou action), la gestion de l’historique des données pour les infos et des actions que l’on peut réaliser pour chaque commande.
Maintenant, nous pouvons retourner dans le fichier javascript et ajouter les trois colonnes :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function addCmdToTable(_cmd) { // Test si le paramètre a été défini if (!isset(_cmd)) { // Initialise _cmd _cmd = {configuration: {}}; } var row = ' \ <tr class="cmd" data-cmd_id="' + init(_cmd.id) + '"> \ <td> \ <input class="cmdAttr form-control input-sm" data-l1key="id" style="display : none;"> \ <input class="cmdAttr form-control input-sm" data-l1key="name"> \ </td> \ <td> \ <span class="type" type="' + init(_cmd.type) + '">' + jeedom.cmd.availableType() + '</span> \ <span class="subType" subType="' + init(_cmd.subType) + '"></span> \ </td> \ <td> \ <span>\ <label class="checkbox-inline"><input type="checkbox" class="cmdAttr checkbox-inline" data-l1key="isHistorized" checked/>{{Historiser}}</label> \ </span> \ </td> \ <td>\ <a class="btn btn-default btn-xs cmdAction expertModeVisible" data-action="configure"><i class="fa fa-cogs"></i></a> \ <a class="btn btn-default btn-xs cmdAction" data-action="test"><i class="fa fa-rss"></i> {{Tester}}</a> \ <i class="fa fa-minus-circle pull-right cmdAction cursor" data-action="remove"></i> \ </td> \ </tr>'; // Ajoute la ligne au tableau $('#table_cmd tbody').append(row); // Ajoute l'identifiant de la commande à la balise <tr> de la ligne $('#table_cmd tbody tr:last').setValues(_cmd, '.cmdAttr'); // Initialise les fonctionnalités de la ligne jeedom.cmd.changeType($('#table_cmd tbody tr:last'), init(_cmd.subType)); } |
Nous avons 4 nouvelles parties :
L’identifiant
1 2 |
<span class="type" type="' + init(_cmd.type) + '">' + jeedom.cmd.availableType() + '</span> <span class="subType" subType="' + init(_cmd.subType) + '"></span> |
L’identifiant de la commande est indiqué dans un champ caché qui sera mis à côté du nom.
Historique
1 2 3 |
<span> <label class="checkbox-inline"><input type="checkbox" class="cmdAttr checkbox-inline" data-l1key="isHistorized" checked/>{{Historiser}}</label> </span> |
Cette case à cocher permet de conserver un historique de la valeur de cette commande.
Actions
1 2 3 |
<a class="btn btn-default btn-xs cmdAction expertModeVisible" data-action="configure"><i class="fa fa-cogs"></i></a> \ <a class="btn btn-default btn-xs cmdAction" data-action="test"><i class="fa fa-rss"></i> {{Tester}}</a> \ <i class="fa fa-minus-circle pull-right cmdAction cursor" data-action="remove"></i> |
Trois balises qui permettent de :
- Configurer la commande,
- Tester la commande,
- Supprimer la commande.
Intégration
1 2 3 |
$('#table_cmd tbody').append(row); $('#table_cmd tbody tr:last').setValues(_cmd, '.cmdAttr'); jeedom.cmd.changeType($('#table_cmd tbody tr:last'), init(_cmd.subType)); |
3 lignes qui configurent la ligne du tableau :
- Ajoute la ligne au tableau,
- Sélectionne la dernière ligne (celle que l’on vient d’ajouter) et configure les valeurs,
- Configure la gestion des types de la commande.
Tests
On peut maintenant ajouter des commandes
Vous pouvez tester les différents éléments, Jeedom s’occupe de la gestion dynamique de la commande.
Nous avons des commandes mais notre équipement n’est pas activé (ni visible), nous allons donc remédier à cela.
Un équipement activé et visible
Ces options s’ajoutent dans le fichier desktop/php/tutoriel.php dans le panneau de commande de l’équipement. Ainsi nous allons ajouter deux champs en dessous de celui du nom.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<fieldset> <!-- Container global d un champ du formulaire --> <div class="form-group"> <!-- Label du champ --> <label class="col-sm-6 control-label">{{Nom de l équipement}}</label> <!-- Container du champ --> <div class="col-sm-6"> <!-- Identifiant caché. --> <input type="text" class="eqLogicAttr form-control" data-l1key="id" style="display : none;"/> <!-- Nom de l'objet--> <input type="text" class="eqLogicAttr form-control" data-l1key="name" placeholder="{{Nom de l'équipement}}"/> </div> </div> <div class="form-group"> <label class="col-sm-6 control-label">{{Etat}}</label> <div class="col-sm-6"> <!-- Case à cocher activant l'équipement --> <label class="checkbox-inline"><input type="checkbox" class="eqLogicAttr" data-l1key="isEnable" checked/>{{Activer}}</label> <!-- Case à cocher pour rendre l'élément visible --> <label class="checkbox-inline"><input type="checkbox" class="eqLogicAttr" data-l1key="isVisible" checked/>{{Visible}}</label> </div> </div> </fieldset> |
Les deux options ont l’attribut data-l1key avec une valeur isEnable pour l’activation et isVisible pour la visibilité.
Lorsque vous actualisez la page, vous aurez la possibilité d’activer votre équipement.
Seulement, rien ne se passe. C’est normal car nous n’avons aucun traitement des actions.
Malgré l’activation de l’équipement, les commandes ne font toujours rien. C’est normal car nous n’avons pas dit à Jeedom comment traiter celles-ci.
Exécuter une action
Lorsque vous cliquez sur Tester, Jeedom exécute une requête Ajax et appelle la méthode execute de la classe tutorielCmd définit dans le fichier core/class/tutoriel.class.php de votre projet.
Pour le moment cette méthode est vide :
1 2 3 |
public function execute($_options = array()) { } |
Pour vérifier si cette méthode est bien appelée, nous allons inscrire un message dans les journaux de Jeedom. Pour cela, ajoutez la ligne suivante :
1 |
log::add('tutoriel', 'debug', 'Exécution d\'une commande'); |
Si vous cliquez sur Tester sur une commande de type action, rien ne se passera, mais vous pourrez retrouver votre message. Pour cela, rendez-vous sur Plugins -> Gestion des plugins. Vous n’aurez plus qu’à cliquer sur le bouton Tutoriel dans la section Log pour voir votre message s’afficher.
On peut ainsi afficher l’identifiant de l’équipement et le nom de la commande :
1 2 |
log::add('tutoriel', 'debug', $this->getEqlogic_id()); log::add('tutoriel', 'debug', $this->getName()); |
Après, on peut lancer un processus ou tout ce que l’on veut d’autre, cependant, il n’est pas pratique de demander à l’utilisateur de créer les commandes une par une.
Créer des commandes par défaut
Nous allons ajouter deux commandes par défaut. La première sera une commande d’état qui fournira une donnée et la seconde sera une action qui actualisera la donnée.
Dans ce fichier core/class/tutoriel.class.php, nous allons maintenant aller dans la classe de l’équipement tutoriel hérité de eqLogic.
Dans cette classe, on peut trouver 8 méthodes particulières. La documentation de Jeedom fournit les informations suivantes :
- preInsert ⇒ Méthode appelée avant la création de votre objet
- postInsert ⇒ Méthode appelée après la création de votre objet
- preUpdate ⇒ Méthode appelée avant la mise à jour de votre objet
- postUpdate ⇒ Méthode appelée après la mise à jour de votre objet
- preSave ⇒ Méthode appelée avant la sauvegarde (création et mise à jour donc) de votre objet
- postSave ⇒ Méthode appelée après la sauvegarde de votre objet
- preRemove ⇒ Méthode appelée avant la suppression de votre objet
- postRemove ⇒ Méthode appelée après la suppression de votre objet
On ne peut pas créer les commandes à n’importe quel moment sinon l’équipement n’existera pas encore ou ce sera trop tard. Généralement, les commandes sont créées dans la méthode postUpdate. Nous allons donc ajouter nos commandes par défaut :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
class tutoriel extends eqLogic { public function postUpdate() { $getDataCmd = $this->getCmd(null, 'data'); if (!is_object($getDataCmd)) { // Création de la commande $cmd = new tutorielCmd(); // Nom affiché $cmd->setName('Données'); // Identifiant de la commande $cmd->setLogicalId('data'); // Identifiant de l'équipement $cmd->setEqLogic_id($this->getId()); // Type de la commande $cmd->setType('info'); // Sous-type de la commande $cmd->setSubType('string'); // Visibilité de la commande $cmd->setIsVisible(1); // Sauvegarde de la commande $cmd->save(); } $getDataCmd = $this->getCmd(null, 'refresh'); if (!is_object($getDataCmd)) { // Création de la commande $cmd = new tutorielCmd(); // Nom affiché $cmd->setName('Rafraichir'); // Identifiant de la commande $cmd->setLogicalId('refresh'); // Identifiant de l'équipement $cmd->setEqLogic_id($this->getId()); // Type de la commande $cmd->setType('action'); // Sous-type de la commande $cmd->setSubType('other'); // Visibilité de la commande $cmd->setIsVisible(1); // Sauvegarde de la commande $cmd->save(); } } } |
On voit ici la création des deux commandes. La première qui s’appellera Données fournit une information de type string. La deuxième est une action comme celle que nous avons créé précédemment.
On peut remarquer setLogicalId qui permet de donner un code à notre commande ce qui permet de traduire les noms affichés. Ce sera ce champ qui sera maintenant vérifier lors d’une requête Ajax.
On peut maintenant créer un objet. Vous aurez deux commandes créées :
Il faudra avant tout activer votre objet et le sauvegarder pour pouvoir les utiliser :
Des commandes qui font des choses
Pour l’exemple, nous allons modifier la valeur stockée dans la commande Données en mettant l’heure à chaque fois que l’on demande un rafraichissement. Nous allons donc modifier la méthode execute :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public function execute($_options = array()) { // Test pour ne répondre qu'à la commande rafraichir if ($this->getLogicalId() == 'refresh') { // On récupère l'équipement à partir de l'identifiant fournit par la commande $tutorielObj = tutoriel::byId($this->getEqlogic_id()); // On récupère la commande 'data' appartenant à l'équipement $dataCmd = $tutorielObj->getCmd('info', 'data'); // On lui ajoute un évènement avec pour information 'Données de test' $dataCmd->event(date('H:i')); // On sauvegarde cet évènement $dataCmd->save(); } } |
Maintenant, nous détectons la commande refresh. Nous allons ensuite rechercher la commande data. Puis nous lui affectons une valeur que nous sauvegardons.
On peut ensuite cliquer sur Tester de la commande Rafraichir, puis Tester sur la commande Données qui vous donnera l’heure :
Mettre à jour régulièrement nos données
C’est bien de forcer le rafraichissement d’une donnée, mais c’est mieux de ne pas avoir à le faire manuellement. Pour cela nous allons utiliser une tâche planifiée. Jeedom utilise le système cron et implémente certaines fonctions afin de faciliter son utilisation.
Pour cela, il suffit de déclarer une méthode dans votre classe tutoriel qui va s’exécuter toutes les 30 minutes :
1 2 3 4 |
public static function cron30($_eqLogic_id = null) { } |
A partir de ce moment, vous pourrez voir que votre plugin utilise des tâches cron :
Ce panneau vous indique également le nom des autres méthodes si vous voulez d’autres tâches planifiées à des intervalles différents.
Maintenant, nous allons juste récupérer l’ensemble des équipements liés au plugin et mettre à jour l’information comme précédemment :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public static function cron30($_eqLogic_id = null) { // Récupère la liste des équipements if ($_eqLogic_id == null) { $eqLogics = self::byType('tutoriel', true); } else { $eqLogics = array(self::byId($_eqLogic_id)); } // Met à jour l'ensemble des équipements foreach ($eqLogics as $tutorielObj) { // On récupère la commande 'data' appartenant à l'équipement $dataCmd = $tutorielObj->getCmd('info', 'data'); // On lui ajoute un évènement avec pour information 'Données de test' $dataCmd->event(date('H:i')); // On sauvegarde cet évènement $dataCmd->save(); } } |
Maintenant, vous pourrez-voir le résultat lorsque la tâche sera appelée. Pour forcer son exécution, vous pouvez aller dans le Moteur de tâches puis exécutez l’action plugin / cron30.
Conclusion
Maintenant, vous devriez avoir les connaissances nécessaires pour vous retrouver dans les fichiers de votre plugin et pour commencer à mettre en œuvre vos projets. Pour aller plus loin, n’hésitez pas à regarder le code source de vos plugins ou ceux accessibles sur GitHub.
Vous pourrez retrouver le code de ce tutoriel à cette adresse : https://github.com/Sylvaner/JeedomPluginTutoriel2