jq: Manipuler les données JSON de Domoticz en shell

 

jq

 

Ayant eu récemment besoin de parcourir un fichier JSON à la recherche de valeurs (parser un json, quoi!), j’ai mis en place l’outil bien connu jq.

Il s’agit d’un programme pour la ligne de commande qui nous dépiaute tout un json et nous renvoie la valeur recherchée.

Site web http://stedolan.github.io/jq/

Euh oui, d’accord mais à quoi ça sert diront les newbies ?

Rappel du fonctionnement Domoticz via l’API JSON.

Domoticz dans son travail quotidien interroge nos périphériques, range les données dans la base de données et met également à notre disposition un moyen de récupérer les valeurs en question.

Cela passe par l’appel d’une URL ou l’on demande l’état d’un dispositif par son idx. (L’idx est consultable dans le menu des dispositifs)

idx_domoticz

 

Ainsi l’appel dans un navigateur de :

http://ip:8080/json.htm?type=devices&rid=35

 

nous renvoie les données concernant le périphérique dont l’idx est 35. Nous recevons quelque chose comme cela :

{
   "5MinuteHistoryDays" : 1,
   "ActTime" : 1432055898,
   "AllowWidgetOrdering" : true,
   "DashboardType" : 0,
   "Latitude" : "44.",
   "Longitude" : "3.146575",
   "MobileType" : 0,
   "ServerTime" : "May 19 2015 19:18:18",
   "Sunrise" : "06:30:00",
   "Sunset" : "21:23:00",
   "TempScale" : 1.0,
   "TempSign" : "C",
   "WindScale" : 1.0,
   "WindSign" : "m/s",
   "dontcachehtml" : true,
    result" : 
    {
         "BatteryLevel" : 255,
         "CustomImage" : 0,
         "Data" : "Open, Level: 93 %",
         "Favorite" : 1,
         "HardwareID" : 3,
         "HardwareName" : "Rfxcommusb10",
         "HaveDimmer" : true,
         "HaveGroupCmd" : true,
         "HaveTimeout" : false,
         "ID" : "0945F16",
         "Image" : "Light",
         "IsSubDevice" : false,
         "LastUpdate" : "2015-05-06 14:06:44",
         ....
        "Status" : "Open",
         "StrParam1" : ""

La partie que j’ai figurée en vert sont sont paramètres globaux Domoticz généralement peu intéressants.

Nous avons besoin plus souvent de récupérer des valeurs dans la partie du bas précédée par « result », comme la valeur de la batterie, le status (Open,On ou Off) , la date de mise à jour…

L’utilitaire  jq va nous aider à cette tâche.

Son rôle est de lire une trame JSON à la recherche d’un nom et de nous renvoyer la valeur associée.

Voyons comment installer et utiliser cet outil

Installation

Depuis les sources

git clone https://github.com/stedolan/jq.git
cd jq
autoreconf -i
./configure --disable-maintainer-mode
make
sudo make install

Sinon comme maintenant (10/2015) jq fait partie des packages pour les distributions Linux les plus populaires, utilisez votre apt-get, yum, …. favori pour installer  jq

ou sinon pour la version 1.5

wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-1.5.tar.gz
tar xfvz jq-1.3.tar.gz
cd jq-1.3
./configure
make
make install

 

Utilisation

En ligne de commande

curl -s "http://192.168.1.82:8080/json.htm?type=devices&rid=35"| jq -r .Sunrise

nous renvoie la valeur du champ Sunrise

curl -s "http://192.168.1.82:8080/json.htm?type=devices&rid=35"| jq -r .result[].Status

nous permettra de récupérer la valeur du champ « Status »

Remarquez qu’il est écrit result[].Status

Le result est le nom du bloc (écrit en noir plus haut) dans lequel je recherche le champ Status, cette ligne me renvoie donc « Open ».

ATTENTION : les majuscules/minuscules sont importantes, il faut vraiment se référer à ce que l’on obtient dans le navigateur.

Un exemple de script sous bash

#!/bin/bash

result=$(curl -s "http://192.168.1.82:8080/json.htm?type=devices&rid=35"| jq -r .result[].Status)


echo $result

if [ $result = "Open" ]
    then
     curl 'http://192.168.1.82:8080/json.htm?type=command&param=switchlight&idx=112&switchcmd=On&level=0'

elif [ $result = "Closed" ]
    then 
          curl 'http://192.168.1.82:8080/json.htm?type=command&param=switchlight&idx=112&switchcmd=Off&level=0'

fi

L’intégration en Lua
Vous trouverez ici un exemple d’intégration dans un script Lua Domoticz

http://www.domoticz.com/wiki/Battery_level_check#Dependencies_-_hardware_.2F_software_.2F_operating_system

Pour toute question technique concernant cet article, veuillez utiliser les forum situés à https://easydomoticz.com/forum/

Mémento instructions shell bash

Cet article fait suite à  https://easydomoticz.com/domoticz-et-scripts-les-bases/ qui tentait de définir les bases du scripting. Ce second opus concerne les commandes Linux usuelles à connaitre pour piloter Domoticz via le shell bash.

Cette liste n’est pas exhaustive et n’empêche pas la lecture de site web spécialisés dans le shell Linux (OpenClassRoom par exemple à des très bons tutoriaux).

Pourquoi écrire des scripts ?

On à besoin d’écrire des scripts quand on commence à s’interfacer avec le monde extérieur, par exemple piloter un ampli via http, récupérer son calendrier google, gérer ses plantes vertes …

C’est la que l’on va avoir besoin d’envoyer des requêtes, récupérer et traiter le résultat, puis mettre à jour Domoticz via l’API JSON.

L’API JSON

« Dans Domoticz vous parlez tout le temps de l’API JSON qu’est ce que c’est ? »

Il s’agit d’un moyen de lecture et d’envoi de données depuis/vers Domoticz.

L’intérêt est de pouvoir interroger ou écrire des données, par le biais de requêtes http, depuis n’importe quel langage (shell, php, python, perl, Lua…) pour peu que l’on respecte le format imposé par Domoticz.

L’API est donc le dictionnaire des commandes que sait comprendre et exploiter Domoticz.

La référence de l’API est ici http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s

Pour utiliser les fonctions de l’API à l’aide du shell Linux nous avons souvent besoin de commandes http, de récupérer des données extérieures…

Voici un petit mémo des commandes récurrentes:

Ecrire et rendre exécutable un script

Ou placer les scripts ?

Il n’y a pas d’emplacement privilégié du moment que domoticz puisse aller lire à cet endroit.

Toutefois les développeurs de Domoticz ont crée domoticz/scripts, domoticz/scripts/lua cela serait quand même logique de les utiliser.

Quitte à créer domoticz/scripts/python, domoticz/scripts/sh, domoticz/scripts/php pour faciliter la gestion des scripts.

Ce qui suit ne s’applique pas aux scripts LUA de domoticz/scripts/lua qui sont entièrement géres par Domoticz et à ce titre doivent correspondre à des “nommages” précis (script_time, script_device…)

Comment écrire un script ?

Tout d’abord quelques considérations générales.

  • Nommez votre script d’un nom explicite et pas toto.py mais clignotement_lampe_exterieur.sh
  • Utilisez les .sh à la fin du fichier, cela n’est pas obligatoire mais pour les pauvres êtres humains que nous sommes c’est mieux.
  • LA chose qu’il faut savoir c’est que votre script doit commencer par un shebang approprié, http://fr.wikipedia.org/wiki/Shebang, en effet les scripts sont des fichiers texte dont la première ligne devra être le shebang qui indique au système dans quel langage est rédigé le script et le chemin vers ce langage. Pour le shell c’est
    #! /bin/bash

Rédaction du fichier.

sudo pico monscript.sh

ouvrira un éditeur de texte qui vous permettra d’écrire vos commandes shell dans le fichier nommé monscript.sh.

  • CTRL k  : permet de couper des lignes.
  • CTRL u : de coller les lignes précédemment coupées.
  • CTRL x  : permet de quitter cet éditeur, une confirmation est demandée.
  • CTRL G : aide du logiciel pico.

Rendre exécutable ce script et le lancer

chmod +x monscript.sh

permet de rendre exécutable votre script.

le lancement se fait par un

./monscript.sh

voici quelques commandes que nous utilisons régulièrement dans des scripts bash.

Appeler une url http

Pour piloter Domoticz on doit appeler une requête http dont l’écriture nous est imposée par l’API Domoticz.http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s

Ainsi pour allumer une lampe dont l’idx est 44

On utilise la commande curl en ligne de commande

curl 'http://192.168.1.81:8080/json.htm?type=command&param=switchlight&idx=112&switchcmd=On&level=0'

Ou dans un script

#! /bin/sh
curl 'http://192.168.1.81:8080/json.htm?type=command&param=udevice&idx=44&nvalue=0&svalue=25;60;2'

envoie 25,60,2 (température, humidité, indice confort) dans l’idx 44 de mon Domoticz, ce qui à peu d’intérêt.

Affecter une variable shell bash

L’idée est de récupérer une valeur de quelque part puis de la réutiliser.

la définition et l’affectation de valeurs d’une variable est faite simplement par son nom.

son utilisation (affichage, tests) est préfixée par « $ »

#!/bin/bash
tempo=$(curl -s "http://domogeek.entropialux.com/tempoedf/now")
echo $tempo

if [ $tempo = "bleu" ]
then
...
tempo=rouge

ici je récupère « bleu », »blanc », ou « rouge » dans la variable tempo en appelant curl.

les tests sont faits sur $tempo= »bleu »

 Envoyer des données dans un fichier

N’importe quelle commande Linux peut être renvoyée à l’intérieur d’un fichier, il suffit de faire suivre la commande de > nom_du_fichier.txt.

l’affichage au lieu de se faire à l’écran se fait dans le fichier.

ainsi un ./domoticz > mon_fichier_log.txt envoie tous les messages Domoticz dans ce fichier.

Afficher des données d’un fichier, d’un port.

Pour afficher les données contenues dans un fichier texte, qui arrivent d’un port ttyXXX, on utilise la commande ‘cat’

cat /dev/ttyAMA0

affiche les données du port série ttyAMAO

cat domoticz.sh

affiche le contenu de ce fichier.

Manipulation de chaines

Extraire une chaîne de caractères entre deux positions précises:

On utilise les symboles ${}.

La syntaxe est ${chaine,position,longueur}

ainsi

chaine=abcdefgh
souschaine=${chaine:4:3}
echo $souschaine

affiche efg (3 caractères à partir du 4eme caractère)

http://pierrellensa.free.fr/dev/bash/www.bsdbooks.net/shells/scripting/fr/string-manipulation.html

Extraire un champ

Cas de figure un peu diffèrent de ci dessus, lorsque je reçois une chaine correctement formatée avec des séparateurs entre chaque champ.

Soit des données telles que :

3A40 mixer volume 30

les champs sont séparés par un espace (3A40espacemixerespacevolumeespace30)
un cut -d’  ‘ -f3 renvoie le 3eme champ de la chaine soit « volume »
et donc cut -d’  ‘ -f4 affiche le 4eme champ soit « 30 » (Attention à l’espace au milieu des simples ‘)

le -d’ ‘ indique le caractère de séparation des champs, ainsi si les champs sont séparés par un caractère @

3A40@mixer@volume@30

cut -d’@’ -f3 affiche  « volume »

 

To be continued

Pour toute question technique concernant cet article, veuillez utiliser les forum situés à https://easydomoticz.com/forum/

La couleur Tempo EDF dans un Widget Domoticz

En utilisant un article ici sur les widget Texte et un article là sur la récupération du tarif tempo EDF depuis api.domogeek.fr on peut faire afficher la couleur actuelle du tarif EDF dans un texte Domoticz :

widget texte domoticz

avec deux lignes comme cela dans un fichier recupedf.sh

Changez mon_idx_du_switch-virtuel par votre Idx à vous (c.f article sur le widget texte)

#!/bin/bash
tempo=$(curl -s "http://domogeek.entropialux.com/tempoedf/now")
curl "http://192.168.1.81:8080/json.htm?type=command&param=udevice&idx=mon_idx_du-switch_virtuel&svalue=$tempo"

 

un chmod +x sur le fichier et un crontab -e plus loin (lancement à 1h10 tous les jours)

10 1 * * * sudo /home/pi/domoticz/scripts/edftempo.sh 2>&1 >> /dev/null

on à ainsi à disposition notre tarif pour d’autres scripts , lua ou blocky.

 

 

Pour toute question technique concernant cet article, veuillez utiliser les forum situés à https://easydomoticz.com/forum/

un terminal dans mon navigateur

Bon on utilise tous putty ou mRemoteng quand on a beaucoup de sessions ssh, RDP, vnc… pour nous connecter à notre Raspberry.

Passant beaucoup de temps devant mon navigateur, je me disais que j’aurais aimé un terminal ssh dans le navigateur directement, certes il y a bien les modules ssh integrés soit à Firefox , soit à Chrome mais je voulais d’un soft intégré au Raspberry et ce fut shellinthebox, un projet google code.


 

shellinabox est un terminal affiché dans un navigateur. Ecrit en Ajax il fournit le « look and feel » d’un vrai shell.

exemple1

Installation

Facile,

sudo apt-get install shellinabox

 

Le fichier de config est  /etc/default/shellinabox.

On peut le modifier pour changer le port par défaut [Default=4200] et qq autres paramètres.

Des fichiers css se trouvent dans /etc/shellinabox.

Ouvrez le port 4200 dans votre parefeu.

Utilisation

Dans votre navigateur tapez  http://ip_du_raspberry:4200

Logez vous comme d’habitude.

exemple2 sitb

Lire la suite

Pour toute question technique concernant cet article, veuillez utiliser les forum situés à https://easydomoticz.com/forum/

Domoticz et lua : appeler une commande shell

L’objectif est de pouvoir déclencher une action liée à l’OS depuis domoticz

On peut bien sur utiliser les Events en mode blocs de Domoticz pour des actions telles que l’envoi de mail, l’ouverture fermeture d’un autre périphérique domoticz.

dooropenlighton.PNG

, lecture http://www.domoticz.com/wiki/Events

 

Mais  parfois on a besoin de taper dans des fonctions plus basses de l’OS, déclencher un script bash, envoyer un tweet…

Dans mon cas lorsque le contact de porte s’ouvre je veux déclencher motion pour faire de la capture vidéo.

Il faut utiliser les scripts lua de domoticz.

Rien de trés compliqué, le wiki de domoticz sur les Events est assez détaillé.

Domoticz range ses scripts lua dans /domoticz/scripts/lua

Ces scripts basés sur des devices DOIVENT se nommer script_device_lenomdemonperipherique.lua

Ici j’ai un périphérique nommé ‘contact porte’

mon script se nomme script_device_contact_porte_actif.lua

print(‘switch vient de passer a on’)

commandArray = {}
if (devicechanged[‘contact porte’] == ‘On’) then
os.execute (‘/etc/init.d/motion start’)
end
return commandArray

il faut toujours mettre un if (devicechanged[‘contact porte’] == ‘etat qui vient de changer’) en tête du script pour s’assurer de déclencher les actions au bon moment.

Le moment crucial de ce script est le os.execute (‘la commande shell’) qui permet donc d’exécuter tout ce que l’on veut pour peu que les droits soient bien appliqués.

Bien sur il faut aussi refaire un autre script dans l’autre sens pour arrêter l’action avec un if (devicechanged[‘contact porte’] == ‘Off’) ….

Pour toute question technique concernant cet article, veuillez utiliser les forum situés à https://easydomoticz.com/forum/