API RESTful du plugin ZWave
Le tutoriel d’aujourd’hui m’a été demandé à maintes reprises depuis plus d’une année. Je vous propose aujourd’hui : d’exploiter l’API RESTful du plugin ZWave.
Le plugin ZWave met à disposition des web services via un serveur REST. Je vais vous apprendre comment l’utiliser afin d’automatiser des tâches de contrôle qualité sur votre réseau Z-Wave.
Cet article est plutôt destiné à des utilisateurs avancés ou du moins avec de bonnes bases du plugin et de jeedom en général. Il fera appel à des notions de programmations en langage PHP.
Des exemples de codes seront disponibles et directement réutilisables si vous ne souhaitez pas écrire de ligne de code. L’idée est déjà de voire les possibilités et j’espère que vous puissiez les exploiter.
Comme dans les reviews de produits, si les grandes explications ne vous intéressent pas, passez directement aux exemples plus bas.
Il ne s’agit pas d’un tutoriel de programmation en langage PHP.
API RESTful ?
Le plugin Z-Wave, se subdivise en différentes parties.
- Un moteur Z-Wave basé sur la librairie openzwave et encapsulé dans un Wrapper Python.
- Une interface web pour la gestion du réseau et des nœuds.
- Des services web permettant d’interagir avec le moteur Z-Wave et d’interroger son réseau Z-Wave via une API RESTful.
Une API RESTful c’est quoi? Il s’agit d’une interface de programme d’application (API) qui utilise des requêtes HTTP pour obtenir des données.
On parle de REST (REpresentational State Transfer) pour définir un style d’architecture pour le développement des services Web.
Jeedom communique avec le moteur Z-Wave via cette API RESTful.
Il nous est donc possible, tout comme pour jeedom, d’exécuter des requêtes sur ce serveur RESTful afin d’automatiser des actions de maintenances ou de contrôles qualités de son réseau Z-Wave.
Je ne vais pas étirer en longueur cette partie, ce n’est pas le but de l’article.
Structure de l’API RESTful
L’API RESTful est décomposé en une série de petits modules. Chaque module aborde une partie sous-jacente particulière du moteur Z-Wave. Cette modularité permet une très grande flexibilité.
Les requêtes ont été divisées en trois grandes familles de ressources.
- Réseau, expose des fonctionnalités générales du réseau comme la santé ou la liste des nœuds.
- Nœud, expose tous les actions et informations à disposition pour chaque nœud, comme tester un nœud ou connaître l’arbre des valeurs.
- Contrôleur, lui expose les fonctionnalités propres à la gestion du contrôleur principal, Ce sont les actions que l’on retrouve dans la page Réseau ZWave.
Nous allons nous attarder plutôt sur les points de terminaison de la famille nœud.
Les points de terminaison?
Alors oui les points de terminaison pour faire très simple c’est la sémantique des mots utilisés pour exploiter les services web RESTful avec leurs jeux de paramètres.
Le serveur reçoit les requêtes et les aiguille au bon sous-système selon les points de terminaison utilisés.
Documentation
Malheureusement par faute de temps et priorité, la documentation (du moins au moment de la rédaction du tutoriel) n’est pas à jour pour cette partie. Je ne vais donc pas m’y référer comme elle concerne l’ancien moteur de 2016.
url
Le serveur RESTful du plugin ZWave écoute les requêtes locales, seulement en provenance de son hôte jeedom. Des considérations de sécurité sont à l’origine de ce choix.
L’url de base :
http://localhost:8083/
Le 8083 étant le numéro de port défini dans l’écran de configuration du plugin ZWave.
Il est recommandé de laisser la valeur par défaut qui est 8083, pour éviter des conflits avec d’autres plugins.
Vous pouvez aussi utiliser 127.0.0.1 à la place de localhost, c’est libre à vous.
http://127.0.0.1:8083
Paramètres
Chaque paramètre est nommé, suivi d’un = puis la valeur du paramètre.
Les paramètres sont séparés entre eux à l’aide d’un symbole &
L’ordre des paramètres n’a pas d’importance.
Paramètres obligatoires
Pour bien sécuriser ces appels, il faudra renseigner une clé unique appelée ZWave API que vous retrouvez dans l’écran de configuration de jeedom sous l’onglet API.
Chaque requête devra obligatoirement avoir le paramètre apikey= avec la valeur de la clé API du plugin ZWave.
En plus de l’apikey certains paramètres ou combinaisons de paramètres sont obligatoires.
Le paramètre type permet d’identifier si on interroge (info) le serveur ou si on souhaite effectuer une action (action).
De façon redondante, un paramètre de type info devra avoir un paramètre info pour identifier l’opération souhaitée.
Et de même pour un type action, un paramètre action devra être présent, toujours pour identifier l’opération que l’on souhaite exécuter.
Ça deviendra plus clair avec les exemples…
Passons maintenant aux trois familles de requêtes possibles via l’API RESTful du serveur ZWave.
Points de terminaison de l’API RESTful du plugin ZWave
Pour avoir une idée générale, je vais vous décrire l’ensemble des différents points de terminaison disponibles via l’API RESTful du plugin ZWave.
Attention : plusieurs sont utilisés pour la gestion du plugin, il sera recommandé de ne pas les exploiter.
Réseau
Les points de terminaison de la famille réseau doivent respecter cette syntaxe :
http://localhost:8083/network?type=info&info=xxx
Les opérations (info/action) possibles sont:
Opération | Description | Remarque |
start | Démarrage du réseau Z-Wave | * |
stop | Arrêt du réseau Z-Wave | * |
writeZWConfig | Ecriture du fichier de cache zwcfg.xml | * |
manualBackup | Faire une copie de sauvegarde du fichier zwcfg.xml | * |
getStatus | Interroger le statut du réseau et ces statistiques | |
getHealth | Récupération de l’état de santé de l’ensemble des nœuds du réseau | |
getNodesList | Récupération de la liste des nœuds du réseau | |
getZWConfig | Récupération du contenue du fichier zwcfg.xml | * |
getOZBackups | Récupération de la liste des sauvegardes de fichier zwcfg.xml | * |
getNeighbours | Récupération de l’information de l’ensemble des voisins |
Attention : Les opérations avec en remarque un * sont propres à la gestion du démon par jeedom. Il est par conséquent recommandé de ne pas les utiliser.
Si je souhaite connaître la liste de nœud du réseau il suffit d’exécuter la requête :
http://localhost:8083/network?type=info&info=getNodesList&apikey=12345abcd12345
En prenant soin de bien remplacer le 12345abcd12345 par sa propre clé API ZWave.
Pour toutes les opérations du point de terminaison de la famille réseau le choix du type n’a pas d’importance. Il doit toutefois être défini, par simplicité vous pouvez toujours utiliser la combinaison type=info&info=mon_operation
Nœud
Les points de terminaison de la famille nœud doivent respecter cette syntaxe,
Pour une requête de demande d’information :
http://localhost:8083/node?type=info&info=xxx
Et pour une action :
http://localhost:8083/node?type=action&action=xxx
On remarque ici un paramètre obligatoire supplémentaire le node_id= il faudra remplacer le x par l’id du nœud.
Les opérations (info/action) possibles sont:
info/action | Description | Type | Remarque |
all | Récupération de toutes les valeurs du nœud (arbre) | info | |
getNodeStatistics | Récupération des statistiques de communication | info | |
getPendingChanges | Récupération du nombre élément en attente d’être appliqué. | info | * |
getHealth | Récupération de l’information de la santé du noeud | info | |
requestNodeNeighbourUpdate | Demande la mise à jour des nœuds voisins | action | |
removeFailedNode | Suppression du nœud si défaillant | action | * |
healNode | Demande la mise à jour des nœuds voisins | action | |
replaceFailedNode | Démarrer le mécanisme de remplacement de nœud défaillant | action | * |
sendNodeInformation | Faire la demande de l’envoi des informations du nœud (NIF) | action | * |
hasNodeFailed | Demande si le nœud est présumé mort par le contrôleur | action | |
testNode | Exécuter un test (ping) | action | |
refreshAllValues | Demande de rafraîchir tous les valeurs du nœud | action | * |
removeGhostNode | Assistant de suppression de module fantôme | action | * |
requestNodeDynamic | Demande de refaire l’étape de l’interview Dynamic | action | * |
refreshNodeInfo | Demande d’envoyer les informations du noeud | action | * |
assignReturnRoute | Forcer une route de retour au contrôleur | action | * |
Attention : Encore une fois, pour les opérations avec en * il est hautement recommandé de ne pas les utiliser.
Important : Les actions sur un nœud sont asynchrones, c’est-à-dire que l’action est demandée au contrôleur et n’est pas exécutée immédiatement. Lorsqu’on lance une requête action au serveur on reçoit tout de même en retour un résultat. La valeur du retour est là pour nous informer que la demande a bien été acceptée par le moteur ZWave.
Je reviendrai plus tard sur les messages de retour et comment les interpréter.
Dans le même ordre d’idée une action sur un module sur pile ne sera exécutée qu’au moment du réveil de celui-ci. C’est bien pour cette raison que toutes les actions sont asynchrones.
En plus des requêtes de type info et action, la famille de points de terminaison nœud contient plusieurs autres possibilités de types:
type | description | paramètres |
refreshClass | Demande de rafraîchir l’ensemble des valeurs d’un nœud pour une classe de commande spécifique. | node_id= cc_id= |
refreshData | Demande de rafraîchir une valeur d’un nœud. On doit spécifier l’id du nœud, la classe de commande, l’instance et l’index de la valeur. | node_id= cc_id= instance_id = index= |
buttonaction | Action sur une valeur de type bouton Le paramètre action accepte les valeurs : press / release | node_id= cc_id= instance_id = index= action= |
setconfig | Permet de modifier un paramètre. | node_id= index= size= value= |
setvalue | Assigner une valeur | node_id= cc_id= instance_id = index= value= |
switchall | Permet de transmettre la commande Switch All Le paramètre state accepte les valeurs : 0 / 1 | state= |
setDeviceName | Définir le nom et la localisation d’un nœud. le paramètre is_enable désactive un nœud si la valeur est 0. | node_id= name= location = is_enable= |
copyConfigurations | Copier les paramètres d’un module source à un module destination. Les deux modules doivent être identiques | node_id= target_id= |
setPolling | Permet d’activer ou de désactiver le rafraîchissement manuel sur une valeur spécifique.
Utiliser frequency=0 pour désactiver ou 1 pour l’activer | node_id= cc_id= instance_id = index= frequency = |
Vous avez déjà été confrontés à ces types dans le mapping de vos commandes.
Pour vous rafraîchir la mémoire :
- setconfig dans le Tuto Modifier les paramètres du module via un scénario
- buttonaction et refreshData dans la Remise à zéro de compteurs d’énergie cumulée
- association Tuto Modifier une association via un scénario
Ce n’est sûrement pas encore clair, ne vous en faites pas j’arrive avec des exemples très bientôt.
Contrôleur
Et pour finir, les points de terminaison de la famille contrôleur devront respecter la syntaxe :
http://localhost:8083/controller?type=action&action=xxx
info/action | Description | Remarque |
hardReset | Remise à zéro complète du contrôleur et du réseau | * |
receiveConfiguration | Activer la réception de la configuration d’un autre contrôleur | * |
transferPrimaryRole | Démarrer le transfert du rôle de contrôleur principal | * |
createNewPrimary | Demande la création d’un nouveau contrôleur principal | * |
testNetwork | Lancer un test (ping) sur l’ensemble des nœuds du réseau | |
serialAPISoftReset | Lancer un reset applicatif du contrôleur | * |
healNetwork | Mise à jour des nœuds voisins pour l’ensemble du réseau | |
cancelCommand | Arrêter une commande l’inclusion ou d’exclusion en attente | * |
writeZWConfig | Écrire le fichier de cache | * |
removeUnknownsDevices | Suppression de modules inconnus du fichier de cache | * |
Attention : je me répète, mais c’est encore plus dangereux ici, pour les opérations avec un * il est totalement déconseillé d’utiliser ces opérations. Une mauvaise manipulation entraîne une perte complète de votre réseau sans retour possible.
Seules les actions healNetwork et testNetwork seront intéressantes pour nous. Elles auraient d’ailleurs dû faire partie du point de terminaison réseau comme ce sont des commandes sur le réseau et non contrôleur.
Résultats
Les requêtes REST communiquent toujours leurs statuts à l’aide de codes d’état HTTP standard.
- 404 ressource demandée n’a pas été trouvée;
- 401 demande n’a pas été autorisée;
- 200 signifie que tout est OK;
- 500 une erreur d’application non gérée sur le serveur.
Donc on s’attend à recevoir un code d’état 200, avec une structure json de donnée en retour d’exécution de la requête.
Tous les retours de requêtes ont une base commune d’information.
{ state : ‘Ok/Error’, result : {} }
Si la requête s’est exécutée avec succès un Ok est retourné dans state. Pour une requête de type info le résultat sera encapsulé dans l’élément result dans une structure json. Le terme state avait été mal choisi, on ne va pas en débattre.
En cas de problème lors de l’exécution, le state sera alors avec Error et l’élément result donne une brève description du problème sous forme de texte, comme par exemple que le nœud n’existe pas dans le réseau. Il ne s’agit pas ici d’une erreur non gérée, c’est l’impossibilité d’exécuter la demande pour diverses raisons.
Les erreurs non gérées par le serveur RESTful retournent avec un code d’état 500 soit en erreur.
J’arrive avec les exemples, voilà c’est maintenant !
Exemples d’utilisations
Bon enfin ce que vous attendiez depuis le début. Les explications et la théorie c’est vraiment ennuyeux.
Je vais vous présenter quelques exemples que je trouve intéressants sur l’exploitation de l’API RESTful dans une utilisation de contrôle qualité de votre réseau.
Pour exploiter l’API RESTful ZWave il faudra faire un peu de code.
Ne partez pas, ça sera simplifié grâce à l’utilisation du moteur de scénario de jeedom.
Si vous ne le connaissiez pas déjà, il est possible d’ajouter un élément Code dans un scénario. Cela permet d’écrire un petit bout de code en langage php.
Pour simplifier la lecture, j’ai publié le code des exemples sur mon github.
Ça sera plus lisible dans l’article et aussi plus facile à maintenir en cas d’amélioration.
J’ai pris soins d’ajouter un maximum de commentaires pour vous en faciliter la compréhension.
Exécuter un Ping
Je vais débuter par un exemple très simpliste, lancer une action pour tester un nœud, ou plus connu, exécuter un ping sur un noeud.
Lorsqu’on exécute un ping sur un nœud, on s’attend à un écho de sa part. Dans le cas de modules sur pile on reçoit une notification que le nœud est endormi.
On peut tester la présence d’un module secteur dans son réseau comme un WallPlug. Si le nœud ne répond pas au ping il a peut-être été débranché ou il est hors de portée du réseau.
Je vais passer en vitesse les étapes de création du scénario et la façon dont il sera déclenché.
Créer un nouveau scénario appelé « ZAPI Ping a Node »
Programmé une fois par heure à la 15ème minute de l’heure.
Le scénario va juste exécuter le code php.
On ajoute un bloc Code.
Qui donne:
Récupérer le contenu du code sur mon github :
Copier-coller le contenu pour obtenir:
On retrouve 2 variables que vous allez devoir paramétrer :
- apizwave, votre clé API du plugin ZWave
- nodeId, l’identifiant de votre nœud à tester.
Le reste pourra être directement utilisé, normalement sans modification.
Que fait le code ?
Je construis un url destiné au serveur local pour atteindre le point de terminaison nœud (node). L’id du nœud sera renseigné via la variable, le type sera une action et l’action elle testNode. Pour finir l’url est complétée par la clé api du plugin ZWave.
$url = 'http://127.0.0.1:8083/node?node_id=' . $nodeId . '&type=action&action=testNode&apikey=' . $apizwave;
L’ordre des paramètres n’est pas important, mais je préfère renseigner la clé api à la fin pour une meilleure lisibilité du code.
La ligne suivante permet d’exécuter et de récupérer le retour de la requête :
Ce retour sera alors décodé en json
Puis j’analyse si l’exécution s’est bien déroulée.
En cas d’erreur, je vais ajouter une entrée dans le log du scénario.
Des erreurs possibles seraient:
- L’id du nœud n’existe pas dans le réseau.
- La clé API est invalide.
- Le contrôleur est trop occupé pour traiter la demande.
Voilà un premier exemple très simple pour débuter.
Vérifier les nœuds présumés morts
En interrogeant l’écran de santé zwave on peut détecter qu’un module est présumé mort.
Nous allons parcourir l’ensemble des nœuds du réseau pour retrouver les modules présumés morts comme le fait l’écran de santé ZWave.
Nous allons créer un nouveau scénario appelé « ZAPI Find Dead Nodes »
On ajoute un bloc Code.
Et le contenu de code :
Il faudra comme à chaque fois adapter la valeur de l’apizwave avec votre clé unique.
La requête, cette fois, demande l’information de la santé pour l’entierté du réseau.
Le contenu est décodé en json puis on valide que la requête s’est bien déroulée.
J’accélère c’est du déjà vu maintenant.
On va parcourir la liste des nœuds
On va tester si le nœud est présumé mort et je m’assure qu’il est aussi toujours actif comme équipement dans jeedom :
Dans ce cas j’ajoute une entrée dans le log du scénario. Puis j’ajoute l’id du nœud à une liste de nœuds en erreur.
Une fois l’ensemble des nœuds parcourus et testés, je sauvegarde la liste des nœuds en erreur dans une variable jeedom pour une utilisation externe à ce scénario.
Cette liste pourra être récupérée dans un virtuel, ou simplement lancer une commande de notification comme un email ou autre pour vous informer du problème.
Surveiller un noeud secteur
Je me souviens d’un utilisateur avec un bassin pour lequel il devait démarrer une pompe plusieurs fois en journée. La vie de ces poissons en dépendait.
Si vous avez une application critique, il faut s’organiser pour pouvoir contrôler la fiabilité des équipements en relations.
Nous allons voir ici une possibilité de suivre un nœud.
Dans le premier exemple on effectue un ping sur un nœud secteur, celui-ci doit retourner une notification d’écho (NoOperation) en retour. On peut imaginer étendre l’exemple avec un test en différé du résultat de la notification.
Les actions sont asynchrones, le retour du ping arrivera quelques secondes après la demande.
Ce délai est variable et je ne souhaite pas faire attendre mon scénario.
Dupliquer le scénario « Ping a Node » pour l’appeler « Check Node Reliability ».
On ajoute vers la fin l’ajout de la sauvegarde du moment de l’exécution du ping.
$scenario->setData("ZAPI_NodePingTime", time());
J’ajoute au scénario un bloc de conditions Si pour tester que le bloc code précédent s’est bien déroulé, je ne souhaite pas tester le retour si le ping n’a pas pu être effectué.
Donc si la variable n’est pas vide, dans 1 minute jeedom exécute le deuxième bloc Code.
Je laisse une grosse minute pour réagir, en général l’écho arrive dans la seconde qui suit la requête.
Récupérer le code du deuxième bloc Code:
Il faudra répéter les informations de la clé API et de l’id du nœud à tester.
Je récupère la date précédemment sauvegardée dans la variable ZAPI_NodePingTime
Et je supprime de suite cette variable. Cette valeur n’est plus utile pour jeedom.
Cette fois je vais interroger la santé du nœud
Je fais les vérifications d’usage si la requête s’est bien passée.
Je récupère le détail de la dernière notification reçue:
Pour des fins de diagnostic j’ajoute au log du scénario la date et la description de la dernière notification reçue.
Un premier test pour déterminer si le nœud est présumé mort suite au test du nœud.
Le deuxième test vérifie un délai trop long de l’arrivée de la réponse, ou plutôt une non réponse à la requête:
Ce cas de figure est plus rare à obtenir, mais il est assez critique, donc il faut le remonter. En général s’il se produit il faudrait même relancer le plugin.
J’ai utilisé longtemps ce scénario pour détecter la fameuse erreur « ERROR: Not enough space in stream buffer » que je n’ai plus depuis que j’ai passé d’une jeedom-Pro à un Intel NUC.
Si l’un des deux tests a renseigné ma variable message c’est qu’il y a eu un problème et que je veux être notifié du problème.
Je récupère une de mes commandes de notification en utilisant la fonction jeedom cmd::byString()
Si la commande existe je l’exécute en renseignant un titre et le message préalablement composé dans un des deux tests.
Si la commande n’est pas trouvé je log le problème, toujours pour fin de diagnostic.
Si le module que je teste fonctionne normalement, dans le log suite à exécution du scénario on retrouve:
Un ping exécuté à 23:07:13. Une tâche est planifiée dans une minute. La sous-tâche démarre, on récupère les informations de la dernière notification. Le retour est arrivé à 23:07:14 donc une réponse après seulement une seconde. Fin normal du scénario.
Si le nœud est débranché ou hors portée suite au ping le nœud devrait passer en présumé mort par le contrôleur.
En cas de dépassement de délai de la notification, je reçois cette notification via Telegram:
Ce mécanisme pourrait aussi prétendre à la détection d’un brouilleur de fréquences radio. Très simpliste, mais si le nœud en question est fiable et répond toujours, une non-réponse pourrait signifier qu’un brouilleur est dans le coin. C’est une fonctionnalité du plugin ZWave qu’on avait pensé au début du plugin mais qui avait été mise de côté.
Pour bien faire il le faudrait tester avec 3 ou 4 modules. S’ils perdent tous ensembles leurs échos un brouilleur est probablement dans les parages.
On peut allez loin, dans la surveillance des nœuds continuons avec un autre exemple.
Essayer de réanimer un nœud
Il peut arriver pour diverses raisons qu’un nœud devienne présumé mort par le contrôleur. Dans de tel cas le contrôleur n’envoie plus de commandes à ce module.
On peut se retrouver avec le chauffage bloqué en marche ou à l’arrêt. Certains vont se souvenir d’avoir perdu de précieux points WAF avec ce genre d’expérience.
Il est en général possible de réanimer la majorité des modules présumés mort. Une action ping sur un nœud présumé mort arrive en général à corriger la situation.
On sait maintenant comment détecter un nœud présumé mort. Vous savez aussi comment exécuter un ping sur un nœud. On peut alors combiner tout ça en bout de code.
Pour situer le contexte de l’exemple imaginons que vous avez 3 modules que vous souhaitez suivre. On récupère leurs Id sur le réseau Z-Wave. L’idée ici est de vous montrer une autre façon d’effectuer des actions sur plusieurs nœuds.
Comme on avance dans les exemples j’ajoute une nouvelle notion. Cette fois je veux interroger plusieurs fois si le nœud est présumé mort, je vais déplacer cette partie de code dans une fonction pour éviter de réécrire le même code plusieurs fois.
Je commence par définir une liste de nœuds que je souhaite tester et réanimer.
Je les parcours un par un
J’appelle ma fonction pour déterminer si le nœud est présumé mort.
S’il est présumé mort je lance un ping sur le nœud en espérant le réanimer.
J’attends quelque secondes pour que les messages soient traités par le contrôleur.
Oui ce n’est pas bien de faire des sleep dans un scénario, il faut les limiter au maximum pour ne pas bloquer jeedom.
Je test à nouveau si le nœud est toujours présumé mort.
Si le ping n’a pas donné satisfaction, je vais essayer cette fois une commande spéciale du contrôleur zwave qui force un reset local du module.
Il ne faut pas faire ce genre d’opération sur une trop grande liste de nœuds, c’est lourd pour le contrôleur Z-Wave et aussi bloquant pour jeedom. Bien entendu, si il n’y a aucun problème cela n’aura aucun impact sur jeedom ou votre réseau.
J’ai volontairement débranché un SmartPlug qui est passé en présumer mort au premier passage.
Puis je le rebranche et j’exécute à nouveau pour essayer de le réanimer
Confirmation que le nœud est présumé mort, puis réanimation suite à l’action du ping sur le nœud.
Il vous est possible d’ajouter des notifications comme on a vu dans l’exemple d’avant, mais ça peut devenir envahissant.
On peut aussi imaginer un compteur d’essai pour ne pas insister sur un module qui est réellement mort et de ne pas générer du trafic inutile à essayer de le réanimer.
Détecteur des nœuds sur piles qui ne répondent plus
On souhaite détecter si nos modules sur piles sont toujours actifs sur le réseau. Un module sur pile dort et ne passe pas en présumé mort de lui-même.
On ne peut pas utiliser les techniques précédemment expliquées.
Dans l’écran de santé ZWave on peut voir si un module sur pile ne s’est jamais réveillé ou a manqué un ou plusieurs réveils.
Nous allons ici exploiter ces informations et s’organiser pour en être informés. Cette approche peut permettre de détecter si un module n’a plus de pile et qu’il n’a pas envoyé l’information de pile faible avant de mourir. C’est un cas de figure très fréquent.
Ce genre de problèmes peut arriver aussi si le maillage n’est pas bon, ou à cause d’une mauvaise couverture du réseau Z-Wave, voir trop de sauts pour rejoindre le contrôleur.
Ce genre de vérification peut être faite qu’une seul fois par jour, si vous avez comme moi des cycles de réveil très espacés sur vos modules.
J’espace au maximum la valeur du Wakeup interval de mes modules comme vous pouvez le constater.
Nouveau scénario appelé « ZAPI Nodes missed wake up » programmé une fois par jour à 10h le matin.
On récupère le code :
On a besoin d’identifier seulement la clé API ZWave, les nœuds sur piles seront retrouvés via l’API. On va voir comment tout de suite.
J’initialise une variable avec la valeur de maintenant.
On exécute une requête pour demander la santé de l’ensemble du réseau.
Le résultat en json contient pour chaque Id de nœud le résultat de la santé du nœud.
On parcourt les nœuds de la liste.
Je m’intéresse seulement au module sur pile, cette information est disponible via la valeur isListening si est égale à 0.
Un nœud Listenning est un nœud qui écoute en permanence, donc sur secteur.
Il vous est possible de désactiver un équipement dans jeedom sans exclure le module, je vais donc valider que l’équipement est bien actif. Je ne souhaite pas être informé qu’un module qui est désactivé dans le fond de mon tiroir ne répond pas.
Certains modules ne se réveillent jamais d’eux-mêmes, il n’est donc pas possible d’attendre d’eux une information sur le prochain réveil. Ces modules seront aussi exclus de mon test.
Je récupère la date du prochain wakeup prévu et je le compare avec maintenant afin de déterminer si l’heure de réveil prévue est dépassée.
Si c’est le cas je log et j’ajoute dans une variable local l’identifiant du nœud en problème.
A la toute fin si j’ai détecté des problèmes je vais stocker la liste de modules sur piles qui ne se sont pas réveillés comme prévu dans une variable jeedom qui sera exploitable dans un autre scénario ou dans un virtuel.
Normalement, si vous avez des modules qui n’ont pas donné de signe de vie dans l’écran de santé vous devriez les retrouver par ce scénario.
On constate que mon Pluviomètre Popp ne s’est pas réveillé comme prévu.
Dans le code j’ai un petit test supplémentaire:
Je regarde si le nœud est actuellement marqué comme étant réveillé. Si c’est le cas, je regarde si ça fait plus de 5 minutes qu’il est marqué réveillé. Un nœud devrait retourner en sommeil prolongé le plus rapidement possible. Cette situation n’est pas normale, je lance une requête afin d’exécuter un test sur le nœud. Le test devrait engendrer une notification « Sleep » soit le sommeil profond.
Attention dans une majorité des cas, le nœud était déjà endormi, c’est seulement la notification au contrôleur qui n’est jamais arrivée. Ce petit contournement permet de remettre en phase les notifications.
Demander une mise à jour forcée de du niveau des piles
Depuis la refonte du plugin l’équipe jeedom adécidé de laisser les modules sur piles gérer eux-mêmes leurs remontées de niveau de piles. Les nœuds devraient le faire eux-mêmes, par conception. Certains nœuds le font très bien tandis que d’autres beaucoup moins bien, voire pas du tout.
On peut donc envisager comme dans le dernier exemple faire un bout de code qui retrouve les modules sur piles actifs et demander une mise à jour forcée de la valeur du niveau de leurs piles.
Cette fonctionnalité a été retirée du plugin pour de bonne raison. En effet elle était vraiment trop gourmande en communication avec les modules. Le niveau des piles était demandé à chaque jour. En final cela occasionnait des communications inutiles pour des remontées journalières avec des valeurs identiques de niveau de piles.
Sur beaucoup de modules on espère une durée de vie d’au moins 2 ans avec la même pile. J’ai des modules qui fonctionnent depuis plus de 5 ans avec les mêmes piles. La perte en pourcentage n’est pas linéaire dans le temps, vous pouvez relire mes différents articles sur les piles et batteries pour plus d’informations.
Fini les justifications de pourquoi on ne devait plus le faire et voilà comment vous pouvez le faire mais de façon optimale.
Nous allons donc créer un scénario appelé « Auto Refresh battery level » qui sera lancé une fois par mois. C’est plus que suffisant.
Vous déciderez vous-mêmes de la fréquence mais évitez d’aller plus bas qu’une fois par semaine.
On récupère le code:
Dans les paramètres configurables, j’ai la date minimum d’un rapport de pile. Elle est calculée sur la date du jour moins 45 jours.
$minimum_date = strtotime("-45 day", time());
Il vous est possible de jouer avec cette valeur, dans l’idée elle doit être plus grande que la fréquence d’exécution du scénario. Avec 45 jours ont obtient au minimum 8 rapports de piles durant l’année.
On retrouve des approches du précédent exemple pour retrouver les nœuds sur piles actifs dans jeedom.
Mais cette fois je vais m’intéresser à la date de la dernière remontée du niveau de la pile. Je cherche à identifier les modules qui remontent d’eux-mêmes leur niveau de pile de ceux qui ne le font jamais.
Je ne veux pas demander une mise à jour du niveau de la pile à un module qui la communique automatiquement et régulièrement. On cherche à diminuer les interrogations inutiles sur son réseau.
Je compare la date du dernier rafraîchissement connu avec la date minimum préalablement calculée, nos -45 jours.
Si le rapport est plus ancien que la date minimum autorisée, je lance une requête de demande de mise à jour de la valeur Battery (CC 128) Level (index 0)
Je me répète, la valeur ne sera actualisée qu’au prochain réveil du module et non à l’exécution de la demande.
Et le scénario passe au nœud suivant et ainsi de suite.
Dans le log d’exécution on peut voir :
Au premier passage j’ai eu plusieurs nœuds qui n’avaient pas envoyé de rapport de pile, plus de 18 si ma mémoire est bonne (je n’avais pas conservé la trace, lors de la préparation). Le lendemain je ré-exécutais manuellement le test pour des fins de validation, plus que 3 nœuds. La fois d’après tous mes modules avaient communiqués leurs rapports de piles.
Avec une fréquence d’exécution chaque mois, vous devriez avoir l’écran des piles mise à jour pour les modules les moins bavards.
Rappel : l’écran des piles de jeedom se met à jour automatiquement dès réception d’un nouveau rapport de niveau de pile, il n’y a plus à attendre le lendemain comme dans le passé.
Mise à jour des nœuds voisins
Une autre fonctionnalité qui a été désactivée et toujours pour des raisons de trafic réseau inutile, spécialement si votre réseau est stabilisé ou que vous ne déplacez jamais vos modules.
Dans l’éventualité que vous apportez des changements dans la topologie de votre réseau, il sera alors intéressant durant quelques semaines de forcer des mises à jour des routes afin d’affiner au mieux la qualité de votre maillage et calcul des sauts afin de rejoindre le contrôleur.
On crée un nouveau scénario, « Heal Network » dans l’exemple je le lance 2 fois par semaine. Il faudra penser à le désactiver manuellement par vos soins après un mois, par exemple.
Le code sera très simple on va appeler la demande de mise à jour des routes pour l’ensemble du réseau.
Récupérer le code :
On avait eu beaucoup de critique lorsque cette fonctionnalité avait été retirée, mais faut vraiment comprendre qu’elle pouvait nuire ou du moins rien apporter de plus à votre réseau sauf de générer du trafic inutile.
Si justement le contrôleur est déjà trop occupé avec d’autres commandes à traiter il est possible dans le log de retrouver:
ZAPI network getHealth return an error: Controller is busy
Sur un gros réseau, faire une demande de mise à jour de voisins peut engendrer plus de 300 messages dans la queue de message du contrôleur. Lorsque la queue de message sature, les commandes l’empilent et prennent plus de temps à être exécutées. On peut avoir de forte latence durant ce genre d’opération. Il sera recommandé de procéder à ce genre de maintenances, seulement à des heures creuses comme en pleine nuit.
Pour revenir au code du scénario, vraiment simple, on appelle la requête du contrôleur healNetwork et c’est le moteur du plugin Z-Wave qui fait le reste du travail.
Ce scénario pourrait être utile si vous déplacez des modules ou si vous en ajoutez ou supprimez régulièrement. Un lancement deux fois par semaine , je pense, la fréquence maximale.
Pensez à désactiver ce scénario, une fois votre réseau stabilisé.
Conclusion
On peut réaliser beaucoup de tâches de maintenance et de contrôles qualité via l’API RESTful du plugin ZWave, beaucoup d’informations sont disponibles sur les modules. Il est possible d’aller beaucoup plus loin, j’ai souhaité rester simple pour ne pas vous perdre dans du code trop compliqué pour rien dans cette article d’introduction.
Lorsque j’étais encore contributeur du plugin c’était vraiment important pour moi ces possibilités d’interaction avec le moteur ZWave et le monde extérieur. C’est une grande force de jeedom cette souplesse à pouvoir aller au fond des choses si on en a envie.
Je vous recommande encore une fois : ne pas utiliser les opérations dangereuses marquées d’une étoile *. Ces opérations sont prévues pour être gérées dans un contexte précis du plugin et ou celui de jeedom.
J’espère que vous avez appris des choses aujourd’hui. Je pourrai revenir sur d’autres possibilités dans des nouveaux sujets, toujours selon vos demandes et commentaires.
Les exemples de codes pourront évoluer dans le temps et voire, j’ajouterai éventuellement de nouveaux exemple.
Je vous souhaite une bonne utilisation de l’API RESTful du plugi Zwave et à la prochaine.
Salut Nechry,
Difficile de laisser un commentaire sur ton blog… c’était pour te remercier pour tous tes tutos et explications sur le Zwave!
J’ai eux quelques problèmes avec les images dernièrement, tu as eux un problème avec les commentaires? Si tu peux détailler, je vais voir pour corriger au mieux.
Dans tout les cas merci de ton commentaire
Bonsoir,
J’ai réalisé un scénario avec ton code pour contrôler les nœuds.
Mon problème est que je dois lancer le code a la main plusieurs fois car moins de 30sec après le lancement et donc la correction du défaut (ping corrige correctement) je dois recommencer.
Tu as une idée @Nechry ?
tu peux stp me dire avec quel exemple et ce que tu souhaites faire ?
Salut,
J’ai utilisé celui ci:
ReviveDeadNodes
J’ai été obligé de finir par désactiver le module car il est complement instable je ne comprends pas. Il bug plusieurs fois a la suite puis plus rien.
Un grand merci nechry, c’est exactement ce que je cherchais ! Parfaitement expliqué à chaque étape pour ceux comme moi qui ne peuvent pas créer mais comprendre le code 😉 Dommage que des options comme vérifier les nœuds morts ou une notification ne soit pas intégrer au plugin Zwave. Encore un grand merci !
Bonjour et un grand merci pour cette article,
J’ai un nœud qui passe en Dead de temps en temps sans vraiment de raison, il n’est qu’à 5 mètres du contrôleur, marche très bien pendant plusieurs jours puis d’un coup se met en Dead et communique plus. C’est le nœud de ma sirène pour mon alarme, alors j’aimerai mieux qu’il marche tout le temps. Du coup j’ai mis en place les 2 scénarios « Heal Network » et « ReviveDeadNodes » en espérant que ça va corriger ce problème.
C’est quand même bizard de perdre le réseau z-wave comme ça ? Une idée peut être ?
alors oui j’ai pas mentionné dans l’article, mais c’est scénarios sont là pour faire des contres mesures en cas de problèmes, mais le mieux reste d’identifier le problème pour le corriger. pour en revenir a ta question, non je n’ai pas d’idée comme ça, sur le pourquoi du quoi. faudrait un peu plus de détails sur les elements en cause, comme le contrôleur, les elements a proximité. si via un dongle une solution qui fait ces preuves est d’utiliser une rallonge usb pour éloigner d’interférences de la box ou autres éléments a proximité.
Bravo et merci pour le partage ! C’est énorme comme boulot, et super clair et utile en plus, donc continue !
Merci pour toutes ces explications et tous les exemples, c’est très clair ! Maintenant y a plus qu’a s’y mettre 🙂
Merci pour tuto.
Je suis arrivé sur ton site via le forum jeedom car beaucoup de problèmes avec des nœuds présumés morts sur des qubino avec fil pilot pour radiateur en format din ou micro module…
Je suis complètement débutant dans la domotique. Alors être confronté à des problèmes de radiateur qui tourne à fond ou pas du tout car nœud mort, je suis complètement perdu et dans un sentiment d’avoir fait une erreur pour piloter mon chauffage malgré un gros investissement.
J’ai lu tout ton tuto, j’avoue avoir vaguement compris l’utilité, surtout dans mon cas pour exécuter un ping, vérifier les nœuds présumés mort et essayer de réanimer un nœud, qui si je comprends bien devrait régler mon problème ?
Par contre tu dis qu’il ne faut pas mettre une trop grande liste de nœud, j’ai 9 zones donc 9 modules donc 9 nœuds je pense. Est-ce un problème ?
Y a-t ‘il une autre solution pour régler ce problème de nœud présumé mort pour mon chauffage que d’effectuer toutes ces lignes de commande ?
Si non je vais essayer de me lancer mais je pense que je vais avoir pas mal de difficultés et probablement beaucoup de questions, n’ayant jamais touché à la programmation…
Merci à toi en tout cas.
Pour 9 noeuds il n’y a aucun problème, tu peux y aller sans autre. Les Qubino fil pilot qui passent en présumé mort, c’est un des cas de figure récurent. Le problème ici dans cette configuration c’est que le Qubino est en général installé très proche du radiateur qui lui est composé d’une grosse surface de metal qui provoque une très grande atténuation du signal. Le mieux serait d’arriver a disposer les micro-modules loin des radiateurs.
Merci pour ta réponse.
Mais si je fais les 3 morceaux de commande, cela va bien arranger le problème ?
Bonjour,
Un commentaire pour te remercier pour ton blog et tes articles afin de faciliter la compréhension du z-wave. Merci pour le tuto qui m’a beaucoup aidé.
avec plaisir, j’ai beaucoup de retard pour de nouveaux articles, mais ça va revenir bientôt.
Est-ce qu’on peut utiliser ce plugin en dehors de Jeedom ?
bonjour, alors techniquement oui tu pourrais lancer l’instance du serveur ZWave et l’utiliser via l’API REST. Par contre tout ce qui est écran de gestion des modules non
Bonjour nechry
Merci pour ce super tuto, je trouve que le zwave est moins stable qu’avant, certes plus rapide mais trop de bugs.
une petite question:
« ZAPI Find Dead Nodes » tu sauvegaardes vers une variable « ZWave_Nodes8death »
Essayer de réanimer un nœud
dans ton code : $nodeIds = array(107, 162, 141);
pourrais remplacer par la variable et surtout comment l’écrire $nodeIds = array(ZWave_Nodes8death); ou $nodeIds = array(variable(ZWave_Nodes8death));
merci
ok j’ai pu récupérer comme ceci
$tabJ = $scenario->getData(ZWave_Nodes_Death);
$nodeIds = array($tabJ);
maintenant s’il y’en plusieurs de dead, je ne sais pas si j’ai automatiquement la virgule entre les modules dans la variable ? exemple (120,130)
oui ils sont séparé par une virgule, c’est cette ligne:
$scenario->setData(« ZWave_Nodes_Death », implode(‘,’, $node_errors));
qui s’en assure.
http://php.net/manual/fr/function.implode.php
Hello Nechry,
Merci pour le tuto 🙂 J’ai un petit souci sur mon Jeedom, il ne se passe rien quand je fais le ping… J’ai bien changé ma clé d’API et tout et tout.
Si je fais un ping sur un équipement à pile sur lequel j’ai enlevé la pile, pour simuler une « panne », j’ai ce retour :
[2019-01-08 20:36:12][SCENARIO] Start : Scenario lance manuellement.
[2019-01-08 20:36:12][SCENARIO] Exécution du sous-élément de type [action] : code
[2019-01-08 20:36:12][SCENARIO] Exécution d’un bloc code
[2019-01-08 20:36:12][SCENARIO] Fin correcte du scénario
Si je fais un ping sur un ID d’équipement qui n’existe pas, là j’ai un bon retour :
[2019-01-08 20:35:40][SCENARIO] Start : Scenario lance manuellement.
[2019-01-08 20:35:40][SCENARIO] Exécution du sous-élément de type [action] : code
[2019-01-08 20:35:40][SCENARIO] Exécution d’un bloc code
[2019-01-08 20:35:40][SCENARIO] ZAPI TestNode return an error: Unknow node id 69
[2019-01-08 20:35:40][SCENARIO] Fin correcte du scénario
Si je fais un ping sur un ID d’équipement présent et fonctionnel, idem je n’ai rien :
[2019-01-08 20:36:12][SCENARIO] Start : Scenario lance manuellement.
[2019-01-08 20:36:12][SCENARIO] Exécution du sous-élément de type [action] : code
[2019-01-08 20:36:12][SCENARIO] Exécution d’un bloc code
[2019-01-08 20:36:12][SCENARIO] Fin correcte du scénario
Ai-je loupé quelque chose? Je mets le bloc de code de mon scénario :
// Setup
// Jeedom configuration/API/Clef API Z-Wave
$apizwave = ‘Fxxxxxxx4DhxxxxxxxxxxxGpNicOxxxxxxxg6ZQ’;
// the node Id to perform the ping
$nodeId = 20;
// End Setup
$url = ‘http://127.0.0.1:8083/node?node_id=’ . $nodeId . ‘&type=action&action=testNode&apikey=’ . $apizwave;
$contents = file_get_contents($url);
//$scenario->setLog(‘Contents :’.$contents);
$results = json_decode($contents);
$success = $results->state;
if ($success != ‘ok’) {
$scenario->setLog(‘ZAPI TestNode return an error: ‘ . $results->result);
}
Merci de ton aide!
Salut Gregoire, petite chose à savoir tu ne peux pas simuler une panne sur un module sur pile. comme d’une façon ou d’une autre il dort et ne va pas répondre au ping immédiatement.
Maintenant ton log retourne: « Unknow node id 69 » comme si tu testes le noeud 69 et non 20.