Aller au contenu
JossAlf

Aide Sur Les Variables Locales

Recommended Posts

 

Bonjour,

 

J'ai un problème avec l'utilisation d'une variable locale...

Je pensais pouvoir affecter une valeur à  cette variable comme suit :

local SqueezeNom = "Cuisine"

if SqueezeNom == 'Cuisine' then
	local player = "00:04:20:2b:81:00 "  
  fibaro:debug(player)
end

if SqueezeNom == 'Salon' then
	local player = "00:04:20:29:bb:3e "
end

if SqueezeNom == 'ChambreB' then
	local player = "00:04:20:2c:0b:fe "
end

if SqueezeNom == 'ChambreH' then
	local player = "00:04:20:2c:35:bc "
end

fibaro:debug(player)
if SqueezeNom == 'ChambreH' then
	local player = "00:04:20:2c:35:bc "
end

fibaro:debug(player)

Le premier debug (ligne 6) me donne bien "00:04:20:2b:81:00"

Mais le second (ligne 26) me retourne une erreur :

[ERROR] 16:53:07: line :debug (arg 2), expected 'string const &' got 'nil'

 
Je comprends pas... C'est comme si la variable locale "player" est tellement localisée qu'elle n'existe que dans le IF .. end ?
 
HELP !!
 

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites
 

J'ai corrigé le problème en passant par une variable globale "de transition" comme ça :

local SqueezeNom = "Cuisine"

if SqueezeNom == 'Cuisine' then
	fibaro:setGlobal('Player' , "00:04:20:2b:81:00 " )  
end

if SqueezeNom == 'Salon' then
	fibaro:setGlobal('Player' , "00:04:20:29:bb:3e ")
end

if SqueezeNom == 'ChambreB' then
	fibaro:setGlobal('Player' , "00:04:20:2c:0b:fe ")
end

if SqueezeNom == 'ChambreH' then
	fibaro:setGlobal('Player' , "00:04:20:2c:35:bc ")
end

local player = fibaro:getGlobalValue("Player")
fibaro:debug(player)

Mais ça remet en question ma compréhension des variables locales que je pensaient valable dans tout le code du module virtuel ou de la scène ?!

 

Si quelqu'un peux me dire si c'est normal ou si c'est un bug. Merci.

Partager ce message


Lien à poster
Partager sur d’autres sites

Salut l'ami!

Alors d'après mes connaissances, après then il faut demander au système de faire une action. Dans ton premier cas tu veux assigner une valeur à  une variable locale. En fait tu ne peux pas sans passer par une fonction fibaro, comme tu l'as fait dans le second cas. Je ne connais pas les squeezebox donc je ne sais pas si je pourrais t'aider en fonction de ce que tu veux faire.

 

Dans ton premier cas la fonction debug te donne une bonne réponse puis une erreur parce que le système lit comme ça:

local SqueezeNom = "Cuisine" -- on assigne le nom Cuisine à  la variable locale SqueezeNom
 
if SqueezeNom == 'Cuisine' then -- si la variable locale porte le nom Cuisine alors
    local player = "00:04:20:2b:81:00 " --[[ ici tu redéfinis personnellement une variable locale nommée player
et tu lui assignes une chaîne de caractère, mais ce n'est pas ton système qui lui assigne automatiquement
car après then il faut une fonction. Local te permet de définir toi même une variable... Donc après ton then
le système ne fait aucune action, il continue la lecture, et ici va juste créer à  ta demande une nouvelle 
variable locale sans rapport avec ce qui précède.--]]
fibaro:debug(player) -- comme tu viens juste de créer ta variable au dessus, il va donc te sortir ta chaîne en debug
end

 -- De la même façon ici aucune action sera réalisée car il n'y a pas de fonction après tes then
if SqueezeNom == 'Salon' then
    local player = "00:04:20:29:bb:3e "
end
 
if SqueezeNom == 'ChambreB' then
    local player = "00:04:20:2c:0b:fe "
end
 
if SqueezeNom == 'ChambreH' then
    local player = "00:04:20:2c:35:bc "
end
 -- jusqu'ici

fibaro:debug(player) --[[ici tu as un message d'erreur car tu as 'end' entre ta création de ta dernière 
variable locale et ta fonction debug. Donc il va lire ta fonction debug comme si il n'y avait rien au dessus. 
Essaye de faire une nouvelle scène avec juste fibaro:debug(player) et tu auras le même message d'erreur.
La lecture du script s'arrête la à  cause de l'erreur précédente.]]--
if SqueezeNom == 'ChambreH' then
    local player = "00:04:20:2c:35:bc "
end
 
fibaro:debug(player)

Je ne sais pas ce que tu veux faire mais si tu veux récupérer des adresses IP de modules virtuels tu peux utiliser la fonction:

deviceIp = fibaro:get(126, "IPAddress")

Partager ce message


Lien à poster
Partager sur d’autres sites

Salut Tom ! Content de te revoir. Ca faisait un bail ! ;)

Je souhaitais assigner le numéro MAC de mes squeezebox en fonction du nom de la pièce passée àune variable locale.

Comme c'est la première fois que j'utilise un if pour modifier la valeur d'une variable locale, je ne savais pas qu'après un then, il fallait une fonction !!!

Mais ce que je ne comprends pas c'est pourquoi en dehors d'un "if then end", local player = "00:04:20:2c:35:bc " fonctionne comme je le souhaite.

J'ai fait un petit MV pour me simplifier les choses et diffuser rapidement des messages.

Tiens je vais le mettre en ligne. Comme ça il pourra être amélioré ;)

En tout cas merci pour ton aide. :74:

MAJ : Lien vers le module virtuel

Modifié par JossAlf

Partager ce message


Lien à poster
Partager sur d’autres sites

Ahhh oui adresse MAC pas adresse IP! M'en lala la poussière de plâtre me fait disjoncter! :13:

Oui je suis pas trop présent sur le forum en ce moment, en plein dans les finitions de la cuisine et du salon!!!

 

Une petite astuce au passage aussi avec les if then else. Il y a aussi elseif qui peut être utilisé aussi souvent que tu veux comme ça.

if ... then
...
elseif ... then
...
elseif ... then
...
elseif ... then
...
else...
 
end

Ca signifie sinon si... Comme ça je trouve que ça fait plus propre, tu vois qu'il y a plusieurs possibilités pour une chose en particulier à  faire, et tu finis une seule fois par end.

 

 

Sinon je ne suis pas un expert mais je crains que tu ne puisses pas modifier la valeur, le nom ou quoi que ce soit d'une variable locale par le système, contrairement à  une variable globale.

 

en dehors du if then end, ta fonction debug va bien t'afficher l'adresse mac puisque le système va lire

local player = "00:04:20:2b:81:00 " -- dans mon tuto sur le lua j'explique qu'il faut imaginer que tu ouvres un tiroir avec une étiquette marquée player, et que dedans tu as un papier avec marqué 00:04:20:2b:81:00
fibaro:debug(player) -- tu demandes au système d'ouvrir le tiroir nommé player et de t'indiquer ce qu'il y a marqué sur le papier simplement 

Le reste du code est faux donc le système lit mais en gros tant qu'il n'y a pas de fonctions il ne fait rien d'autre que d'ouvrir ton tiroir player et de changer le numéro inscrit sur le papier. Si il rencontre à  nouveau une fonction fibaro:debug(player) juste après que tu ais crée une nouvelle variable locale player, il va te donner cette nouvelle valeur que tu as assignée.

L'erreur que tu as eu c'est qu'entre le moment où tu as crée ta variable locale en 18 et ta fonction debug en 21, tu as un end qui a terminé une condition commencée en 17 (mais qui ne marchera pas car on ne peut pas changer une variable locale par le système) donc le système ne tiens plus compte de ce qu'il y a au dessus du end.

 

Essaye dans une nouvelle scène de mettre juste

if SqueezeNom == 'ChambreH' then
    local player = "00:04:20:2c:35:bc "
end
 
fibaro:debug(player)

ou

fibaro:debug(player)

et il t'indiquera le même message d'erreur, car dans sa lecture du script, ça ne veut rien dire, il lui manque des éléments ou les choses ne sont pas dans le bon ordre.

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci Tom.

Je comprends mieux la nécessité de passer par une variable globale. Mais ça reste un peu ésotérique comme fonctionnement. Je m'y pencherai plus en profondeur. Je n'aime pas rester dans le flou ...

Pour les elsif, je ne les ai pas utilisés sciemment car j'avais cru lire quelque part que ça ralentissait le code ?! Mais je ne sais pas où j'ai lu ça ? À confirmer ou infirmer donc ;)

En tout cas, Mon module virtuel fonctionne parfaitement bien et me facilite la vie (pour confirmer la bonne réception des ordres) :)

Ça me fera un super complément au GEA de Steven. :)

Partager ce message


Lien à poster
Partager sur d’autres sites

Ah je ne sais pas pour les elseif, mais moi j'ai lu un message de Krikroff qui dit qu'avec ses 10 milliards de lignes de codes la box avait toujours autant de patate donc moi j'hésite pas :P

Partager ce message


Lien à poster
Partager sur d’autres sites

J'avais eu de lui la même réponse quand je m'interrogeais sur l'impacts des mains loop ;)

Partager ce message


Lien à poster
Partager sur d’autres sites

Je vais sur le tchat si tu veux échange gare sur ces variables locales...

Partager ce message


Lien à poster
Partager sur d’autres sites
 

Bon alors j'ai trouvé !

 

Le problème venait du mot "local" avant le nom de la variable "player" !!

Apparement ça ne plaisait pas à  la HC2 ?!

 

Donc ce code est faux et retourne une erreur sur le second fibaro:debug(player)

if 0 == 0 then
    local player = "OK" 
    fibaro:debug(player)
end

fibaro:debug(player)

En revanche ce code est bon et retourne bien OK sur les 2 debug.

if 0 == 0 then
    player = "OK" 
    fibaro:debug(player)
end

fibaro:debug(player)

On peut donc bien modifier la valeur d'une variable locale avec un simple IF...  :74:

Je me suis donc pris la tête pour une erreur de syntaxe !!! Je suis passé par une variable globale inutile ...  :13:

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Héhé dans ton exemple si tu ne mets pas "local" tu crées une variable globale donc cela fonctionne.

 

Créer une variable local dans une condition "If" équivaut a créer un variable dans une fonction. Cela signifie que sa visibilité est réduite à  la condition même. Ce qui est logique si on prend l'exemple suivante

si ( je murmure à  l'oreille de JossAlf) then
   local mon_message = "C'est un secret"
end

fibaro:debug(mon_message) -- Il en sait rien puisque c'est un secret

Par contre, si on déclare proprement ces variables locales, il n'y aura aucun soucis

local player = nil

if (true) then
  player = "Coucou" 
end

fibaro:debug(player)

Ainsi le script à  une visibilité sur la variable local player et peut la modifier. Cette dernière reste local à  l'environnement ou elle a été créée. Si je fait

fonction coucou()
   local player = "Mon player dans ma fonction"
   fibaro:debug(player) -- je suis dans la fonction, je connais donc player
end

debug:fibaro(player) -- connait pas car player est local à  ma fonction et là , je n'y suis pas.

J'espère que cela peux aider.

 

Donc ton code propre et optimisé donnera 

local payer = nil

if SqueezeNom == 'Cuisine' then
	player = "00:04:20:2b:81:00 "  
elseif SqueezeNom == 'Salon' then
	local player = "00:04:20:29:bb:3e "
elseif SqueezeNom == 'ChambreB' then
	local player = "00:04:20:2c:0b:fe "
elseif SqueezeNom == 'ChambreH' then
	local player = "00:04:20:2c:35:bc "
end


-- Ou
--Bien plus joli

local Squeezers = {
   ['Cuisine']  = "00:04:20:2b:81:00 ",  
   ['Salon']    = "00:04:20:29:bb:3e ",
   ['ChambreB'] = "00:04:20:2c:0b:fe ",
   ['ChambreH'] = "00:04:20:2c:35:bc ",
}

fibaro:debug(Squeezers["Cuisine"])


Partager ce message


Lien à poster
Partager sur d’autres sites

Merci Steven. 

 

Est-ce que dans ton exemple suivant on est en variable locale tout le temps ?

Autrement dit : est-ce que le fait de l'avoir déclaré player en variable local par local player = nil permet d'utiliser "player" dans et en dehors de If (true) ... end ou cela ne change rien à  mon problème ?

Par contre, si on déclare proprement ces variables locales, il n'y aura aucun soucis

local player = nil

if (true) then
  player = "Coucou" 
end

fibaro:debug(player)

Partager ce message


Lien à poster
Partager sur d’autres sites

La variable locale est disponible dans le bloc dans lequel elle est déclarée alors que la variable globale (normalement définie a l’extérieur des blocs ou fonctions) elle est utilisable dans tous les blocs ;).

 

Dans le HC2 une scène, un bouton ou même le main loop c'est un bloc ! Donc ici l'utilisation d'une variable locale n'a d’intérêt que si tu codes des fonctions :)

 

Et je suis bien d'accord avec Steven pour la forme suivante:

local Squeezers = {
['Cuisine'] = "00:04:20:2b:81:00 ",
['Salon'] = "00:04:20:29:bb:3e ",
['ChambreB'] = "00:04:20:2c:0b:fe ",
['ChambreH'] = "00:04:20:2c:35:bc ",
}

Partager ce message


Lien à poster
Partager sur d’autres sites

Bon je pense que je commence à  comprendre mais il me reste un doute...

 

Je reprends pour être certain : 

local player = nil
 
if SqueezeNom == 'Cuisine' then
	player = "001 "  
elseif SqueezeNom == 'Salon' then
	player = "002 "
end

fibaro:debug(player) 

Ce code signifie :

Ligne 2 : Je crée une variable locale appelée "player"

Ligne  4 : Si SqueezeNom vaut "Cuisine" alors

Ligne 5 : ma variable (locale qui valait nil) se voit affectée maintenant "001"

Ligne 6 : mais si SqueezeNom vaut "Salon" alors

Ligne 7 : ma variable (locale qui valait nil) se voit affectée maintenant "002"

Ligne 8 : fin

 

Ligne 10 : Affiche en debug la valeur de ma variable locale player -> soit 001 si SqueezeNom = Cuisine ; soit 002 si SqueezeNom = Salon et Nil si squeezeNom est mal renseignée.

 

C'est bien ça ?

 

 

Si j'avais oubliée la ligne 2 "local player = nil", la HC2 aurait interprété les lignes 5 et 6 comme la création d'une variable GLOBALE appelée player.

Alors que là  on utilise player comme variable LOCALE. C'est bien ça ?

 

 

PS : désolé mais quand je fais le boulet je fais pas semblant...  :P

Partager ce message


Lien à poster
Partager sur d’autres sites

En gros, c'est bien ça  :60:

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Bravo :60:

Partager ce message


Lien à poster
Partager sur d’autres sites

Bon alors dernière question :

if SqueezeNom == 'Cuisine' then
	player = "001 "  
elseif SqueezeNom == 'Salon' then
	player = "002 "
end
 
fibaro:debug(fibaro:getGlobalValue("player")) -- variable globale
fibaro:debug(player) -- pas bon -> génère une erreur parce que player en local n'existe pas !

D'après ce code (comme je n'ai pas déclaré de variable locale) je n'ai qu'une variable GLOBALE créée à  la volée.

 

Voici ma question :

Je croyais qu'il fallait passer par le panneau de gestion des variables pour créer les GLOBALES (à  moins que ce ne soit que pour pouvoir gérer visuellement leur valeur) ?

Celle-ci n'apparaitra d'ailleurs pas sur le panneau ? 

 

Je sais je suis compliqué...  :13:

Partager ce message


Lien à poster
Partager sur d’autres sites

Maintenant que j'ai compris, je trouve ça super subtile en fait :

local player = "001"
  fibaro:debug(player) 

if 0 == 0 then
	local player = "002 "  
  fibaro:debug(player)
end
  fibaro:debug(player)

donne ça au debug 

[DEBUG] 13:20:44: 001
[DEBUG] 13:20:44: 002 (création d'une nouvelle variable au sein du if qui n'est pas la même que celle créée à  la ligne 2)
[DEBUG] 13:20:44: 001 (on reste sur la valeur donnée lors de la création ligne 2)

 

On voit que l'on a 2 variables locales player qui n'ont pas les mêmes valeurs !

 

Alors que ça :

local player = "001"
  fibaro:debug(player) 

if 0 == 0 then
	player = "002 "  
  fibaro:debug(player)
end
  fibaro:debug(player)

Donne ce résultat au début :

[DEBUG] 13:22:55: 001
[DEBUG] 13:22:55: 002
[DEBUG] 13:22:55: 002

 

On voit que l'on a bien qu'une variable locale

 

et enfin ça :

--local player = "001"
--fibaro:debug(player) 

if 0 == 0 then
local player = "002 "  
  fibaro:debug(player)
end
  fibaro:debug(player)

Retourne au debug :

[DEBUG] 13:25:53: 002
[ERROR] 13:25:53: line :debug (arg 2), expected 'string const &' got 'nil'

 
 
Car on a créé à  la volée un variable locale qui n'existe que entre IF et END
​Et que le dernier debug cherche une variable LOCALE qui n'a jamais été déclarée avant le IF
 
 
OUF... je crois que j'ai compris !  :60: 
  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Il y a variable globale en terme de programmation (ce que nous avons précédemment décrit) et les variables de la HC2 qui en réalité sont des données stockées dans une base.

Partager ce message


Lien à poster
Partager sur d’autres sites

ok !

Donc la valeur d'une variable stockée dans la base de la HC2 s'obtins par 

fibaro:getGlobalValue("player")

Alors que la valeur d'une variable globale créée dans un code s'obtient comme une variable locale ?

fibaro:debug(player)

Peut donc s'employer pour afficher le contenu d'une variable locale et globale créée dans un code !

Partager ce message


Lien à poster
Partager sur d’autres sites

Oui, ils ont appelé cela variables globales mais en réalité ce sont des données partagées.

Partager ce message


Lien à poster
Partager sur d’autres sites

En fait toute mon incompréhension vient de ce panneau de variables !

Je croyais que les variables globales ne pouvaient être créées QUE depuis ce panneau sous la HC2.

Et que toutes les autres variables créées au sein du code ne pouvaient être QUE LOCALES !

 

Ben là  j'ai fait fort moi ! Je commençais à  me dire que c'était super alambiqué comme gestion des variables...  :P

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci Steven , Krikroff et Tom.

Me voilà  rassuré. Il faut seulement que je détruise tous les schèmes* que j'avais mis en place dans mon esprit depuis hier !!!  :D

 

 

* Larousse : Ensemble de concepts permettant de se faire une image de la réalité en résumant les éléments disparates de cette réalité à  l'aide d'instruments fournis par la raison.

Partager ce message


Lien à poster
Partager sur d’autres sites

Après avoir bien lu toutes ces explications, je me rappelle maintenant du concept de base en programmation, qui est appelée portée des variables. Je ne crois pas avoir vu Krikroff ou Steven mentionner ce concept, mais je suis certain que vous connaissez parfaitement ça. Pourtant c'est bien de ça qu'il s'agit dans le cas présent.

 

Finalement c'est le défaut des langages trop permissifs comme le LUA, le PHP, etc, qui permettent d'utiliser des variables sans les déclarer explicitement, avec comme conséquence des résultats imprévisibles, obligeant à  mettre beaucoup de debug pour comprendre l'origine du problème. Avec des langages genre le Pascal où l'on était obligé de déclarer très précisément chaque variable, il n'y avait plus d’ambiguà¯té possible.

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

×