Cours complet Lua API Manuel en PDF


Télécharger Cours complet Lua API Manuel en PDF

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


Cours et exemples pour reviser Lua API

...

Programmer :

Programmer (ou bien scripter) consiste à écrire des instructions dans un langage qui est à la fois compréhensible facilement par un humain et transformable de manière à être compris également par l'ordinateur.

Car le but de la programmation est bien de donner des instructions (le programme) à l'ordinateur et surtout à son processeur afin que celui-ci en retour agisse sur notre application (lise un fichier, déplace un objet de jeu, etc...).

La transformation du langage de script en langage compréhensible par l'ordinateur s'appelle la compilation. Cette partie prend plus ou moins de temps suivant les langages et à moins d'avoir de très très nombreux scripts, devrait prendre moins d'une seconde en Lua.

Le processeur est très doué lorsqu'il s'agit de faire des calculs mathématiques ou logiques, mais ne sait pas réfléchir. C'est pourquoi nous devons lui dire par écrit (grâce au script) comment traiter l'information qu'il reçoit du jeu et de l'utilisateur et quoi faire avec le résultat de tout ses calculs.

 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.

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 –11

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

–11

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 :

 %% globals –11

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 :

--LL

%% properties

%% globals

–11

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 :

 %% 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:

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

--LL

%% 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.

 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

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.

 Lua conserve toutes ses variables globales dans une table ordinaire, appelée table d'environnement.

?

for n in pairs(_G) do print(n) end

Les paragraphes suivants, vous permettront d'apprendre plusieurs techniques utiles pour manipuler cette table d'environnement.

_G: Accéder aux variables globales avec des noms dynamiques.

En règle générale, l'affectation est suffisante pour obtenir et définir les variables globales.

Mais la difficulté survient lorsque vous voulez manipuler une variable globale dont le nom est stocké dans une autre variable, ou lorsque vous voulez la calculer au moment de l'exécution.

Pour obtenir la valeur de cette variable, de nombreux programmeurs sont tentés d'écrire quelque chose comme:

?

loadstring("value = " .. varname)() ou bien

value = loadstring("retour " .. varname)()

Si par exemple, varname a la valeur connue x, la concaténation se traduira par "retour x " (ou "value = x", avec la première forme).

Cependant, ces codes impliquent la création et la compilation d'un nouveau morceau de code et beaucoup de travail supplémentaire.

Vous pouvez accomplir la même chose avec le code suivant, beaucoup plus court et bien plus efficace que le précédent.

?

value = _G[varname]

Puisque l'environnement est une table ordinaire, vous pouvez simplement l'indexer avec le nom de la variable.

De la même manière, vous pouvez assigner directement une variable

globale en écrivant:

_G[varname] = valeur.

Mais attention:

Certains programmeurs quelque peu excités par ces fonctions peuvent

arriver à écrire:

_G["a"] = = a _G["var1"], qui est juste une manière compliquée d'écrire var1

Une généralisation du problème précédent est de permettre d'accéder à tous les champs (mots, caractères...etc.) contenus dans un nom dynamique, comme "io.read" ou "a.b.c.d".

Vous résoudrez ce problème avec une boucle qui démarre à _G et évolue, champ par champ.

?

function Getfield(f)

local v = _G -- début de la table _G for w in string.gmatch(f, "[%w_]+") do v = v[w]

end

return v

end

La fonction string.gmatch(), de la bibliothèque string, itère tous les mots contenus dans f. (où "mots" est une séquence d'un ou plusieurs caractères alphanumériques et/ou de soulignement).

La fonction correspondante utilisée pour définir des champs est un peu plus complexe.

Une affectation comme a.b.c.d.e = v est équivalente à:

?

local temp = a.b.c.d temp.e = v

Autrement dit, pour récupérer le dernier nom, vous devez gérer le dernier champ séparément.

La fonction suivante Setfield() créer également des tables intermédiaires dans un chemin où elles n'existent pas.

?

function Setfield(f, v)

local t = _G -- on démarre avec la table Globale

for w, d in string.gmatch(f, "([%w_]+)(.?)") do

if d == "." then -- pas le dernier champ? t[w] = t[w] or {} -- on créer une table si absente

t = t[w] -- get the table

else -- dernier champs

t[w] = v -- on assigne

end

end end

Ce nouvel exemple capture le nom du champ dans la variable w et un point optionnel dans la variable d.

Si un nom de champ n'est pas suivi par un point, c'est qu'il est le dernier.

Avec la fonction précédente, l'appel à Setfield("t.x.y", 10) crée une table t globale, et une autre table t.x, et assigne 10 à t.x.y



102