Introduction à la programmation en LUA sur la box domotique Fibaro Home Center 2 

Dans cette introduction, vous apprendrez les bases de la programmation de scènes via le langage Lua.

AJOUT DE SCÈNE EN LUA

La nouvelle API permet de programmer des scènes en langage de programmation de scripts LUA.

Lors de la création d'une nouvelle scène, vous pouvez choisir si la scène sera mis en place dans les blocs ou via un script LUA.

 

Créer une scène en LUA avec le Home Center 2

 

Ecriture et déboguage de script LUA avec le Home Center 2 de Fibaro 

Saisir le script LUA dans la fenêtre d'édition de code.

LUA fonctionne comme d'autres langages de programmation avec des lignes les unes au dessus des autres.
Si vous connaissez déjà d'autres langages de programmation, il n'est pas ici nécessaire de finir les lignes par un symbole (vous pouvez tout de même finir par une virgule mais LUA l'ignorera).

Chaque scène écrite en LUA doit toujours commencer avec cette entête :

 
--[[
%% properties
%% globals
–]]

L'en-tête est absolument indispensable pour n'importe quelle scène.

Sous le titre "%% properties" sont définis les "trigger" / "déclencheurs" et sous le titre "%% globals" sont définies les variables globales

Tout ceci sera décrit plus en détail un peu plus loin. 

LE MATÉRIEL

Vous devez d'abord comprendre le fonctionnement de l'API pour les différents types d'équipements.

Voici les principaux :

 

Les modules / appareils ajoutés au panneau "modules" du Home Center 2 sont indiqués avec type spécifique :

  • binary_light – Simple relais ON/OFF par exemple.
  • dimmable_light – Variateur (dimmer) ou certaines sirènes Fortrezz par exemple.
  • blind – Volets roulants, rideaux motorisés, etc.
  • virtual_device – Dispositif virtuels préalablement créés par l'utilisateur.
  • thermostat_setpoint – Têtes thermostatiques (Danfoss Linving Connect par exemple).
  • motion_sensor – Détecteurs de mouvements.
  • door_sensor – Détecteur d'ouverture (porte, fenêtre, etc.)
  • smoke_sensor – Détecteur de fumée.
  • water_sensor – Détecteur d'inondation.
  • ip_Camera – Caméra IP.

 

 

Avec la nouvelle API, les périphériques du système sont caractérisés par:

  • deviceID = Un numéro unique attribué par le HC2 et définissant le module,
  • Type = Le type de périphérique (ex: binary_light)
  • properties = Ses propriétés (ex: valeur, lien mort) : Donne l'état de l'appareil (détection de mouvement, interrupteur allumé, volet ouvert, etc). Ces valeurs sont en lecture seule. (détecteur de mouvement est compromise, l'interrupteur marche / arrêt est allumé et que l'obturateur est ouvert)
  • actions = actions (turnON(), turnOFF(), setValue()) : des actions qui peuvent être effectuées sur l'appareil (allumer : turnON(), éteindre  turnOFF(), fixer un niveau d'allumage de la lampe setValue() ).  

La liste des API par appareils est disponible ici (articles en Polonais sur le site de Fibaro, la traduction sera proposée ultérieurement)

NOTRE PREMIER SCRIPT EN LUA (fonction "call")

Nous allons commencer par une action simple : commander un module de type commutateur ON/OFF.

Pour ce faire, nous allons utiliser une des fonctions les plus élémentaires du HC2 : "call" (demander).

Vous trouverez plus d'informations sur la commande "Call" ici (article en Polonais)

Cette action s'écrit comme ceci : fibaro:call(deviceID, actionName, …)

Elle envoie une demande d'action à un équipement / module.

Elle prends au moins deux arguments :

  • deviceID – Le numéro identifiant du module
  • actionName -  Le nom de l'action (ex: TurnOn, TurnOff, SetValue) - Les actions possibles dépendent des appareils et sont listées ici:

Exemple avec un micro-module commutateur (exemple: FGS211) dont l'ID serait "2" :

--[[
%% properties
%% globals
–]]

fibaro:call(2, 'turnOn') -- nous allumons le module dont l'identifiant est 2

La première partie du script est l'entête standard (ligne 1 à 4), la deuxième partie contient les actions (ligne 6)

Vous pouvez indiquer des commentaires derrière des doubles tirets '--'
Tout ce que vous écrivez après les doubles tirets ne sera pas exécuté, il est très utile de commenter votre code pour faciliter sa compréhension lors d'une relecture ultérieure ou par une autre personne.
 

Une fois la scène enregistrée via le bouton "Enregistrer", vous pouvez lancer votre scène à l'aide du bouton "Démarrer".

Ce script sera exécuté à chaque fois que vous cliquerez sur "Démarrer" 

SCRIPT 2 (fonction "sleep")

Ce script permet d'allumer le module avec l'identifiant 2 et de l'éteindre après 3 secondes.

Nous allons utiliser la fonction "sleep" documentée ici.

Elle s'écrit comme ceci : fibaro:sleep(time) , l'argument "time" étant en milisecondes il faudra indiquer la valeur 1000 (ms)  fibaro:sleep(1000)

Le script ressemblera donc à ceci :

--[[
%% properties
%% globals
–]]

fibaro:call(2, 'turnOn') -- allume la lampe
fibaro:sleep(3000) -- attend 3 secondes
fibaro:call(2, 'turnOff') -- éteind la lampe

SCRIPT 3 (fonction "debug")

Une autre fonction très utile est fibaro:debug. Cette fonction est un outil de déboguage très utile, il permet au développeur de contrôler exactement où le programme en est de son execution et permettre un deboguage rapide. Veuillez noter que dans Lua (comme dans tous les langages de programmation) le code du programme est exécuté ligne par ligne.

Description détaillée de la fontion "Debug"

Elle s'écrit comme ceci : fibaro:debug(text)

Lorsque vous exécuterez votre script, les informations de déboguage s'inscrirons sur l'écran noir en dessous du script.

Exemple :

--[[
%% properties
%% globals
–]]

fibaro:debug('Hello world!)

Va afficher ‘Hello world’ sur l'écran de déboguage.

SCRIPT 4 (setValue)

Dans cet exemple, nous allons utiliser les 3 fonctions vues précédemment (call mais cette fois complétée par un "setValue", wait et debug).

Nous souhaitons lors de notre départ de la maison exécuter le scénario suivant : fermer les volets en deux étapes avec un éclairage pendant l'opération, puis l'extinction de cet éclairage puis la fermeture totale du volet.

Utilisation de la fonction déjà vue "fibaro:call" mais complété par un "setValue" à 50%, ce qui donne : fibaro:call(10, ‘setValue’, ’50′)

Liste des équipements de notre exemple :

  • Relais commutateur ON/OFF (deviceID 2) - Eclairage complémentaire
  • Variateur (deviceID 5) - Eclairage principal
  • Volet roulant (deviceID 10) 
--[[
%% properties
%% globals
–]]

fibaro:debug('Démarrage du programme')
fibaro:debug('J\'allume le relais ID 2')
fibaro:call(2, 'turnOn') –- Allume le relais avec deviceID 2
fibaro:debug('J\'attends 5 secondes')
fibaro:sleep(5000) -- Pause de 5 secondes
fibaro:debug('Les 5 secondes sont passées, je vais baisser le volet à 50%')
fibaro:call(10, 'setValue', '50') -- On baisse le volet à 50%
fibaro:debug('Volet en mouvement')
fibaro:debug('j\'attends 5 secondes')
fibaro:sleep(5000) -- On attends 5 secondes
fibaro:call(5, 'setValue', '75') -- On fixe le variateur à 75%
fibaro:debug('L\'éclairage est réglé')
fibaro:debug('Nous allons éteindre l\'éclairage')
fibaro:call(2, 'turnOff') -- On éteints l\'eclairage complémentaire
fibaro:call(5, 'turnOff') -- On éteints le variateur 
fibaro:debug('Nous allons fermer les stores)
fibaro:call(10, 'turnOff') -- On ferme les stores
fibaro:debug('Tous les appareils sont éteints')
vous remarquerez le caractère "\" --> "antislash" ou "barre oblique inversée" dans certains commentaires.

En effet c'est ce qu'on appelle un caractére d'échapement nécessaire pour que le système n'interprète pas l'apostrophe comme la fin du texte.

Exemples :

  • fibaro:debug('mon texte de déboguage sans apostrophe')  -- pas de problème ici
  • fibaro:debug('ici j'ai mis une apostrophe sans échapemment') -- le système ne comprendra pas tout ce qui suite la deuxième apostrophe (qui indique la fin du texte), c'est à dire la phrase "ai mis une apos ..." va faire boguer le système. 
  • fibaro:debug('ici j\'ai mis une apostrophe avec échapemment') -- ici, pas de problème, la 2e apostrophe est ignorée et la fin du texte est signalée par la 3e apostrophe.

SCRIPT 5 (les variables)

Dans cet exemple nous allons voir comment récupérer l'état / valeur d'un module (allumé, éteint, pourcentage d'ouverture, etc.).

Nous allons nous prendre pour exemple un relais commutateur FGS211 avec pour deviceID 2.

Ce module possède de nombreux paramètres mais pour le moment nous allons nous intéresser uniquement à la proprité "value".

"value" renvoie une valeur qui indique l'état de l'apareil (ex: 0 = éteint, 1 = allumé)

Pour cela nous allons utiliser la fonction fibaro:getValue documentée ici.

Exemple d'utilisation : fibaro:getValue(deviceID, propertyName).

Maintenant, nous allons passer à la prochaine information très importante:

Pour stocker une valeur dans n'importe quel langage de programmation vous utilisez ce qu'on appelle des variables. La variable est un concept, qui dans les langages de programmation (y compris LUA) a trois caractéristiques - le type, le nom et la valeur.

Voici la structure des variables en LUA (plus d'informations ici)

local MaVariable
 

Nous devons déclarer les variables locales. Elles ne sont visibles que dans notre script.

Les variables sont un élément essentiel d'un langage de programmation, elles permettent de stocker des valeurs numériques ou des chaines de caractères (texte).

Il est possible de stocker dans une variable une valeur provenant de l'état d'un module.

local MaVariable = fibaro:getValue(2, 'value')

Récupère l'état (0 = éteint, 1= allumé) de notre module deviceID 2 et stock cette valeur dans la variable "MaVariable"

 

Exemple :

--[[
%% properties
%% globals
--]]

local MaVariable --Déclaration de la variable "MaVariable"

fibaro:debug('Nous allumons l\'appareil 2')
fibaro:call(2, 'turnOn') --Allumage de l'appareil 2
MaVariable = fibaro:getValue(2, 'value')
fibaro:debug('Ma variable a pour valeur: ' ..MaVariable)
fibaro:debug('Nous allons maintenant éteindre notre appareil 2')
fibaro:debug('dans 3 secondes')
fibaro:sleep(3000)

fibaro:call(2, 'turnOff')
fibaro:debug('Extinction en cours')
fibaro:sleep(3000)
MaVariable = fibaro:getValue(2, 'value')
fibaro:debug('Ma variable a pour valeur: ' .. MaVariable)

fibaro:debug('Nous allumons de nouveau notre module')
fibaro:call(2, 'turnOn')
fibaro:sleep(3000)
MaVariable = fibaro:getValue(2, 'value')
fibaro:debug('Ma variable a pour valeur: ' .. MaVariable)

  • Premièrement nous déclarons la variable (ligne 6),
  • nous allumons l'appareil 2 (ligne 9),
  • nous stockons l'état de l'appareil récupéré par la fonction "getValue" dans la variable précédemment créé (ligne 10),
  • nous affichons le contenu de la variable dans le débogue en ajoutant ..MaVariable après le texte délimité entre les apostrophes (ligne 11).
  • fibaro:debug('Ma variable a pour valeur: ' ..MaVariable) donnera sur l'écran de débogue : [DEBUG] 17:57:55: Ma variable a pour valeur: 1 

Il aurait aussi été possible de regrouper les étapes des lignes 6 et 10 en tapant :

local MaVariable = fibaro:getValue(2, 'value') 

SCRIPT 6 (fonction IF)

Maintenant, nous introduisons un autre élément de langages de programmation qui est IF. Une instruction conditionnelle permet d'exécuter du code de programme, sous certaines conditions, qui est dans l'exemple ci-après, SI (IF) l'appareil deviceID 2 est allumé ALORS (THEN) allumer le deviceID 3.

  • if (état) then
  • instruction
  • end

Ce qui donne :

--[[
%% properties
%% globals
--]]
local MaVariable –-déclaration de la variable "MaVariable"

fibaro:call(2, 'turnOn') --j'allume l'appareil 2
MaVariable = fibaro:getValue(2, 'value')

if (MaVariable == '1') then
  fibaro:call(3, 'turnOn')
end

  • On déclare la variable (ligne 5),
  • on allume l'appareil 2 (ligne 7),
  • on récupère l'état de l'appareil 2 et le stockons dans "MaVariable" (ligne 8),
  • si (if) "MaVariable" est égale (==) à "1" alors (then) (ligne 10) allumer l'appareil 3 (ligne 11) fin de la condition IF (end) (ligne 12).
  • Si la valeur de MaVariable était à "0" alors le programme serait allé directement après le "end" donc dans le cas présent à la fin du programme (sans allumer l'appareil 3).

SCRIPT 7 (fonction ELSE)

Nous avons un détecteur d'ouverture dont le deviceID est 145, il possède de nombreuses propriétés comme par exemple le niveau de charge de sa pile, s'il est armé, etc ...).

Nous n'allons pour le moment nous intéresser qu'à la propriété "Value" (0 = fermé / intact , 1 = ouvert / violé).

 

Si nous voulons vérifier l'état du capteur nous pouvons utiliser la commande suivante :

fibaro:getValue(145, 'value')

 

Si nous voulions savoir si le capteur est armé, nous aurions utilisé la commande suivante:

fibaro:getValue(145, 'armed')

 

Dans les deux cas, le résultat est une valeur binaire 0 ou 1.

--[[
%% properties
%% globals
--]]

local MaVariable1 = fibaro:getValue(145, 'value') –-stock la valeur du capteur 145 dans MaVariable1
fibaro:debug('value = ' .. MaVariable1) –-Affiche la valeur de MaVariable1
local MaVariable2 = fibaro:getValue(2, 'value') –-stock la valeur de l'interrupteur 2 dans MaVariable2
fibaro:debug('value = ' .. MaVariable2) –-Affiche la valeur de MaVariable2

if (MaVariable1 == '1') then
 if (MaVariable2 == '0') then
  fibaro:call(2, 'turnOn')
 else
  fibaro:call(2, 'turnOff')
 end
end

Autrement dit (lignes 11 à 19):

  • SI le capteur de porte est ouvert
  • ALORS :
  • SI la lampe est éteint ALORS l'allumer 
  • SINON éteindre la lampe
  • FIN (du SI n°2)
  • FIN (du SI N°1) 

SCRIPT 8 (les trigger)

Pour le moment nous n'avons montré que des script qui nécessitaient d'être executés manuellement mais il pourrait être intéressent de les déclencher automatiqument en fonction d'un événement.

C'est là qu'entre en scène les trigger (déclencheurs). 

Exemple: nous voudrions que la lumière s'allume automatiquement lorsque le capteur détecte un mouvement.

local MaVariable --je déclare MaVariable

MaVariable = fibaro:getValue(50, 'value')
if (MaVariable == '1') then
  fibaro:call(3, 'turnOn')
end

Ce qui signifie :

  • SI le capteur de mouvement 50 est en alarme (mouvement détecté)
  • ALORS allumer la lampe 3.

Le problème c'est que ce script devrait s'exécuter en permanence (en faisant des boucles) pour fonctionner mais ce n'est pas une bonne solution.

Nous voudrions que ce script s'execute lorsque le capteur passe en détection de mouvement, pour cela nous allons utiliser le déclancheur "TRIGGER" 

Pour cela nous allons devoir déclarer dans l'entête le DeviceID du capteur (50), suivi de la propriété servant de déclencheur (value):

--[[
%% properties
50 value
%% globals
–-]]

 

Maintenant, à chaque fois que la propriété "valeur" du capteur changera (détection ou fin de détection), le programme s'exécutera.

La condition SI servira quand à elle à vérifier s'il s'agit bien d'une détection de mouvement (value == 1) et pas une fin de détection (value == 0) 

--[[
%% properties
50 value
%% globals
–-]]

local MaVariable –-déclaration de MaVariable

fibaro:debug('démarrage du programme')
MaVariable = fibaro:getValue(50, 'value')
if (MaVariable == '1') then
 fibaro:call(3, 'turnOn')
end

Si nous voulons aussi éteindre la lumière lorsque que le capteur passe en "fin de détection" (value == 0), il suffit d'ajouter quelques lignes :

--[[
%% properties
50 value
%% globals
–-]]

local MaVariable –-déclaration de MaVariable

MaVariable = fibaro:getValue(50, 'value')
if (MaVariable == '1') then
 fibaro:call(3, 'turnOn')
else
  fibaro:call(3, 'turnOff')
end

SCRIPT 9 (os.date) 

Ce script est conçu pour allumer deux lampes dans un intervalle de 5 secondes l'une de l'autre après ouverture de la porte; de plus cette scène doit fonctionner uniquement entre 15h et 18h.

--[[
%% properties
<CapteurPorte> value
%% globals
--]]

local Maintenant = os.date("*t")

if (Maintenant['hour'] >= 15 and Maintenant['hour'] <= 18) then
 fibaro:call(<lampe1>, 'turnOn')
 fibaro:sleep(5000)
 fibaro:call(<lampe2>, 'turnOn')
end

Pour connaitre les autres fonctions liées aux dates et heures vous pouvez consulter la documentation sur LUA.org 

local Maintenant = os.date("*t") --stocke la date et heure actuelle du système sous forme d'un tableau à l'intérieur de la variable "Maintenant" 

 

Il est possible de récupérer les champs suivants stockés dans ce tableau : 

year Année
month Mois de 01 à 12
day Jours de 01 à 31
hour Heures de 00 à 23
min Minutes de 00 à 59
sec Secondes de 00 à 59
isdst est binaire, renvoie "true" si nous sommes en heure d'été

 

Pour comparer l'heure actuelle avec nos horaires de consigne on utilise la ligne suivante avec un "AND" (et):

if(Maintenant['hour'] >= 15 and Maintenant['hour'] < 18) then

La condition est : si il est (Maintenant) "15h ou plus" et "moins de 18h" --> donc entre 15h et 17h59 

Dans le cas d'une plage horaire se situant sur deux dates, typiquement entre avant minuit et après minuit, nous devons utiliser la ligne suivante avec un "OR" (ou):

if( Maintenant['hour'] >= 23 or Maintenant['hour'] < 4)

La condition est : si il est (maintenant) "23h ou plus" ou "moins de 4h" --> donc entre 23h et 3h59.

 

Pour compléter ce tutoriel :


Mis à jour le : 27/04/2016 à 20:52 Auteur : Jérôme Massiaux, technicien domotique-store.fr



Les nouvelles questions sont affichées en même temps que la réponse du technicien. Nous répondons généralement en moins d'une journée ouvrée, néanmoins, certaines questions peuvent nécessiter des tests ou recherches complémentaires et augmenter ce délai. Nous nous réservons le droit de ne pas publier ni répondre aux questions de service après-vente concernant un produit n'ayant pas été acheté sur notre boutique.