Aller au contenu
Berale64

De L'utilisation Des Triggers

Recommended Posts

Je continue mon apprentissage de la HC2 et j'investigue les triggers (en français gâchette ou détente).

Dans notre domaine c'est donc un évènement qui, lorsqu'il intervient, va déclencher une action.

 

J'avais fait un petit script qui affiche les températures min et max à  l'intérieur de la maison et à  l'extérieur.

http://www.domotique-fibaro.fr/index.php/topic/3438-temp%C3%A9rature-min-max/

 

Il est en fait très peu efficace du point de vue ressources machines puisqu'il est basé sur une boucle infinie qui, à  interval régulier, va chercher les températures, même si elles n'ont pas changé.

 

Je l'ai donc modifié en utilisant les triggers, et c'est maintenant un changement de température qui actionne la scène pour afficher les nouvelles valeurs.

 

Dans l'entête sous "%% properties" il faut indiquer les IDs des devices concernés et exit le "while true do".

--[[
%% autostart
%% properties
35 value
42 value
%% globals
--]]

Comme la scène ne tourne pas en continue, il faut enregistrer les valeurs min/max dans des variables globales.

Vous devez créer GVTempE et GVTempI.

également json.encode ne fonctionne pas dans les scènes (suis en 3.600) je le fais moi même.

 

Voilà  le code complet:


--[[
%% autostart
%% properties
35 value
42 value
%% globals
--]]

local temp;
local TempExtMin;
local TempExtMax;
local TempSalonMin;
local TempSalonMax;
local str;


local id = {};

id.tempext = 35;
id.tempint = 42;
id.display = 83;

-- GVTemp format 099.99/-99.99


GVTempE = fibaro:getGlobal("GVTempE");
GVTempI = fibaro:getGlobal("GVTempI");
-- fibaro:debug(GVTempE);
-- fibaro:debug(GVTempI);

TempExtMin = tonumber(string.sub(GVTempE,1,6));
TempExtMax = tonumber(string.sub(GVTempE,8,13));
TempSalonMin = tonumber(string.sub(GVTempI,1,6));
TempSalonMax = tonumber(string.sub(GVTempI,8,13));

  
  -- Température extérieur
  
  temp = fibaro:getValue(id.tempext,"value");
 -- fibaro:debug(temp);
  if (tonumber(temp) < TempExtMin)
    then
     TempExtMin = tonumber(temp);
    end
  if (tonumber(temp) > TempExtMax)
    then
     TempExtMax = tonumber(temp);
    end
   str = string.format("%3.1f",TempExtMin).." / "..string.format("%3.1f",TempExtMax);
   fibaro:call(id.display, "setProperty", "ui.Label1.value", str.." °C");
   fibaro:call(id.display, "setProperty", "ui.Label7.value", temp.." °C");
   str = string.format("%06.2f",TempExtMin).."/"..string.format("%06.2f",TempExtMax);
   -- fibaro:debug(str);
   fibaro:setGlobal("GVTempE",str);

-- temérature intérieur
  
  temp = fibaro:getValue(id.tempint,"value");
  -- fibaro:debug(temp);
  if (tonumber(temp) < TempSalonMin)
    then
     TempSalonMin = tonumber(temp);
    end
  if (tonumber(temp) > TempSalonMax)
    then 
     TempSalonMax = tonumber(temp);
    end
   str = string.format("%3.1f",TempSalonMin).." / "..string.format("%3.1f",TempSalonMax);
   fibaro:call(id.display, "setProperty", "ui.Label11.value", str.." °C");
   fibaro:call(id.display, "setProperty", "ui.Label13.value", temp.." °C"); 
   str = string.format("%06.2f",TempSalonMin).."/"..string.format("%06.2f",TempSalonMax);
  -- fibaro:debug(str);
   fibaro:setGlobal("GVTempI",str);

le code du bouton reset du VD est aussi changé.

Il remet les variables globales à  099.99/-99.99

Changer le numéro de la scène (23) et du VD (83) ou mettre un getSelfId.

fibaro:killScenes(23);
fibaro:setGlobal("GVTempE","099.99/-99.99");
fibaro:setGlobal("GVTempI","099.99/-99.99");
fibaro:sleep(1000);
fibaro:startScene(23);

local Date =  os.date("%d/%m/%y %H:%M");

fibaro:call(83, "setProperty", "ui.Label5.value",Date);

Depuis que j'ai une HC2, je regarde avec plus d'attention les script LUA et je vois énormément de boucles infinies quand des triggers seraient beaucoup plus efficaces.

 

Un petit clien d'oeil à  Jojo qui semble aimer les VD. Il faut lire la petite phrase concernant la "Boucle principale".

 

Boucle princiaple

Dans la boucle principale, vous pouvez entrer le code LUA qui doit être exécuté chaque seconde.

 

Dans ta version des températures, tu actives ce script toutes les secondes, alors que les températures changent en gros toutes les 20 à  30 minutes. (mes fgk sont réglés tous les 0.5°)

 

Je pense également au tuto de sebcbien sur les dead nodes. Je n'ai pas fait le test, mais il semble qu'il est possible de faire un script avec sous %% properties des choses comme.

35 dead

42 dead

69 dead

 

etc ....

Et de faire une scène qui ne s'actionnera que s'il y a un dead node.

 

Ces considérations me sont venues en lisant vos posts sur la température de vos HC2. Je me demande s'il n'y a pas trop de boucles qui tournent pour rien, ou pas grand chose, et surchauffent le CPU.

 

PS: En me relisant, j'ai peur de passer pour un donneur de leçons, ce n'est certainement pas le cas, mais juste des pistes de réflexions.

  • Upvote 4

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci Berale24 pour cette analyse pleine de bon sens.

Je vais y regarder de plus près dès que j'ai un peu de temps

Partager ce message


Lien à poster
Partager sur d’autres sites

Perso je préfère aussi travailler avec des scènes dès que c'est possible, et garder les VD pour la commande et le retour d'état.

donc:

VD -> bouton -> set Variable globale

Scène surveille VG et prend action quand il faut

VD a une boucle dans le main loop qui surveille la VG et modifie l'icône, le texte et en fonction.

Avantages:

- Beaucoup plus portable et partageable, facilité de migration vers la V4 et ré-installant tout et ceux qui copieront e code n'auront qu'une VG àcréer

- Actionnable àpartir d'aures scènes sans devoir récupérer l'id du bouton et du VD, juste une VG a récupérer (et qui aura toujours le même nom...)

- Status analysable par d'autres Scènes et VD.

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Berale oui les trigger c'est bien plus efficient que les boucles infinies, bravo pour ta démarche :)

 

Cependant concernant la chauffe de la HC2 cela n'a pas d'impact, car nos box sont toutes à  moins de 10% de charge CPU, et même proche de 1%.

D'ailleurs une box sans rien (après recovery) chauffe tout autant.

C'est le processeur qui veut ça, même au repos.

 

Pour finir, les boucles infinies de module virtuel on un sleep forcé de 3s par sécurité, car au tout début, il n'y avait pas cette sécurité et certains scripts ont vraiment fait planter quelques box en les surchargeant.

Partager ce message


Lien à poster
Partager sur d’autres sites

1%, ah! ben zut alors, j'aurai du garder la HCL :D

 

Je vous joins l’icône que j'utilise pour la scène min/max.

 

post-1115-0-16902200-1422876559_thumb.png

Partager ce message


Lien à poster
Partager sur d’autres sites

Dans l'entête sous "%% properties" il faut indiquer les IDs des devices concernés et exit le "while true do".

 

Berale24,

Comme le fait remarquer Lazer, quand j'ai mis le script pour le calcul des temp min et max dans une VD au lieu de dans des scènes, je n'utilisais déjà  plus le "while true do", car le main loop de la VD fait déjà  cela tout seul.

Par contre, en effet et en théorie, c'est selon moi bien mieux ta proposition de trigger. Mais si le CPU de la box reste à  <10%, il ne me semble pas utile d'ajouter cette complexité pour une optimisation théorique. L'avantage de tout avoir dans la VD, est que c'est facile de faire un export, et que le json fonctionne  (et qu'il ne faut pas utiliser une astuce pour les scènes (que au demeurant, je garde en mémoire)), et qu'il ne faut pas hardcoder l'ID de la scène

 

Sur le temps que j'écris ceci, je vois ta réponse, et je te pique illico ton icône.

Partager ce message


Lien à poster
Partager sur d’autres sites

 J'étais aussi tombé sur cette icône dans ma recherche google.

Mais je viens de faire un mix avec le thermomètre de Fibaro.

Temp Min Max

Il y a du texte en blanc que l'on voit apparaître avec le fond de l'interface.

Partager ce message


Lien à poster
Partager sur d’autres sites

il y a quand même une chose qu'il faut faire attention avec les triggers.

Si on en met beaucoup (pour vérifier les nœuds morts par exemple) et que en un coup on en a 6 (une multiprise greenwave par exemple) on va avoir 6 scènes concurrentes qui vont se lancer pile en même temps, àquelques mili secondes d’intervalles.

Il peut donc y avoir une surcharge massive en un temps court.

On peut tester pour que la scène ne puisse pas se lancer en parallèle mais on risque de passer àcôté d'events.

Inconvénient aussi, par exemple dans une boucle pour vérifier les nœuds morts, il faut déclarer tous les id en entête, donc revenir sur le script àchaque ajout/suppression de device...

économique en resources, mais pas très plug&play àmon avis

Partager ce message


Lien à poster
Partager sur d’autres sites

@sebcbien, pas de risques de surcharge le HC2 est capable d' encaisser sans broncher ;) ce n'est pas un RPI... Pour la perte d'events et bien tout va dépendre de la conception du code dans la scène.

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Oui elle est puissante c clair, mais une boucle toutes les minutes, dans cette optique est sans doute plus propre si on n'est pas très fort en programmation.

 

Imaginons que il y a un problème d'antenne, ou que la puce zwave est plantée et que les 100 devices zwave apparaissent morts en même temps et que pour chaque noeud mort on a demandé un push, un email  et ... (non pas de prise de photo sur la cam 1 :P  )... il y a intérêt à  avoir prévu le coup !

Quand je vois que ma box plantait avec le module alarme de fibaro quand il y avait une intrusion (cligotement des lampes, et push de photos)... si je ne l'arrêtait pas dans les 30 secondes bah seul un reset hardware pouvait la récupérer...

Partager ce message


Lien à poster
Partager sur d’autres sites

@krikroff

 

En parlant de ça, aurais-tu un bout de code qui permet de passer ces triggers (qui lancent une Xe fois la scène) d'être passés à  la première  ?

Moi jusqu'ici je ne peut que détecter avec countscene et faire un exit si >1

Partager ce message


Lien à poster
Partager sur d’autres sites

C'est bien connu que si l'on confie le même projet à  deux informaticiens, on aura deux choses totalement différentes et que les deux sont convaincus d'avoir la meilleure solution !!! :D

 

En ce qui me concerne, j'aime approfondir les choses et utiliser les outils mis à  ma disposition.

 

Mais toutes les solutions sont respectable, et d'autant plus si l'auteur est content de lui.

Je revois toutes mes scènes en trigger à  partir du moment ou le temps n'intervient pas.

Et je me disais, qu'à  la limite, on pourrait avoir une seule scène de temps qui mettrait à  jour des variables globales qui serviraient de trigger aux scènes qui font le boulot !!! :60:

Partager ce message


Lien à poster
Partager sur d’autres sites

Moi je rajouterais gea dans la chaîne ;-)

Sent From my Vic20

Partager ce message


Lien à poster
Partager sur d’autres sites

Certainement. Je rajouterais GEA quand j'aurais bien compris le fonctionnement de la Box et du LUA.

Partager ce message


Lien à poster
Partager sur d’autres sites

Très intéressant ;) Petite question bête, mais question tout de même :

 

peut on trigger des variables globales ?

Partager ce message


Lien à poster
Partager sur d’autres sites

Oui on peut trigger des variables globales.

 

Mais attention, une petite limitation : une variable globale modifiée via le panneau de variable ne déclenchera pas le trigger.

Il faut donc modifier les variables via des modules virtuels ou des scènes, et utiliser le  panneau de variable uniquement pour la création (ou suppression) de celles-ci.

Partager ce message


Lien à poster
Partager sur d’autres sites

Berale24 j'adhère totalement à  ton analyse vis-à -vis de l'utilisation des triggers.

 

J'ajouterais même qu'il est encore possible d'optimiser des scripts en identifiant l'id du trigger avec la fonction fibaro:getSourceTrigger().

 

Dans ton cas ce n'est pas forcément nécessaire car tu cherches des min et des max.

Mais si par exemple tu veux enregistrer l'historique des températures sur tout un mois, il est possible de n'enregistrer que la valeur de température du périphérique qui a changé et uniquement lui... du coup tu économises en nombre d'enregistrements sur ta variable globale... Je sais pas si je suis bien clair...

 

Voilà , c'était juste pour t'aider à  aller plus loin dans ta découverte des triggers...

Partager ce message


Lien à poster
Partager sur d’autres sites

je constate que depuis la V4, la propriété 'varName' sur un trigger de type variable ne remonte plus rien.

Avez vous le même problème ?

Partager ce message


Lien à poster
Partager sur d’autres sites

Un autre petit pour la route !

Supervision des piles.

Steven nous a déjà  publié un module beaucoup plus sophistiqué que celui que je vous propose, mais je suis toujours dans les Triggers, non compatible avec l'approche de Steven.

Il est en liaison direct avec ma config mais adaptable très facilement.

Donc, toujours une scène et un VD pour l'affichage.

Il faut dans l'entête de la scène déclarer les ID des devices à  pile.

Attention, il s'agit de l'ID du maitre.

post-1115-0-04285000-1423146165_thumb.jpg

 

Déclaration des devices:

--[[
%% autostart
%% properties
40 batteryLevel
62 batteryLevel
52 batteryLevel
34 batteryLevel
37 batteryLevel

%% globals
--]]

Si la charge d'une des piles est inférieure à  30%, l’icône tourne au rouge.

J'ai piqué l’icône bleu à  Steven ( :94: ) et j'en ai fais une rouge.

Voilà  la scène complète:

--[[
%% autostart
%% properties
40 batteryLevel
62 batteryLevel
52 batteryLevel
34 batteryLevel
37 batteryLevel

%% globals
--]]


idVDpiles = 86;

local idbat = {40,62,52,34,37};  --id pour piles
local icons = {"1015","1019"};

local low = 1;


  -- Piles
  fibaro:debug("run");
  for i = 1,#idbat do
    val = fibaro:getValue(idbat[i], "batteryLevel");
    fibaro:debug(val);
    if (val == "255") then val = "0"; end
      fibaro:call(idVDpiles, "setProperty", "ui.Label"..i..".value", val.." %"); 
    if (tonumber(val) < 31) then
      low = 2;
    end
  end    

   fibaro:call(idVDpiles, "setProperty", "currentIcon", icons[low]);
  

Pour les IDs des icones, merci Krikroff et son HC2 Toolkit. :wub:

 

post-1115-0-25970300-1423146503_thumb.pngpost-1115-0-01788000-1423146523_thumb.png

 

post-1115-0-24296700-1423146686_thumb.jpg

 

Batteries.vfib

  • Upvote 2

Partager ce message


Lien à poster
Partager sur d’autres sites

à  implémenter dès mon retour à  la maison ce soir !

Merci :60:  :60:  :60:

Partager ce message


Lien à poster
Partager sur d’autres sites

Oui on peut trigger des variables globales.

 

Mais attention, une petite limitation : une variable globale modifiée via le panneau de variable ne déclenchera pas le trigger.

Il faut donc modifier les variables via des modules virtuels ou des scènes, et utiliser le  panneau de variable uniquement pour la création (ou suppression) de celles-ci.

 

Bon... après quelques vaines tentatives de trigger sur deux variables globales, je vous soumets mon script de scène LUA :

 

Lâchez vous sur ce qui ne convient pas, moi je bloque trop à  cette heure ci :(

--[[
%% properties
PRESENCE values
GLOBALE_FERMETURE values
%% globals
--]]

local jour = os.date("%Y:%M:%D");
local heure = os.date("%H:%M");
local status = "";
local status_volets = "";

local startSource = fibaro:getSourceTrigger();
if (
    if ( tonumber(fibaro:getGlobalValue("PRESENCE")) == tonumber("1"))
        then status="Présent";
    elseif ( tonumber(fibaro:getGlobalValue("PRESENCE")) == tonumber("2"))
        then status="Absent";
    elseif ( tonumber(fibaro:getGlobalValue("PRESENCE")) == tonumber("3"))
        then status="Repos";
    else status="unknown";
    end

    if ( tonumber(fibaro:getGlobalValue("GLOBALE_FERMETURE")) == tostring("ouverts"))
        then status_volets="Ouverts";
    elseif ( tonumber(fibaro:getGlobalValue("GLOBALE_FERMETURE")) == tostring("fermes"))
        then fibaro:debug(" Volets fermés");
    end
    )
or
startSource["type"] == "other"
)
then
    fibaro:debug("------------------------------------------------------");
    fibaro:debug("Statut de présence : "..status);
    fibaro:debug("Statut des volets : "..status_volets);
    fibaro:debug("------------------------------------------------------");
end
  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

qu'est-ce qui ne va pas ?

 

Mais ce que je vois de bizarre (SANS garantie, car je suis le débutant en LUA par excellence)

ligne 16 (18 et 20) : je trouve qu'il y a beaucoup de tonumber inutiles. J'aurais écris :

if (fibaro:getGlobalValue("PRESENCE") ==1)

et aux lignes 25 et 27, tu sembles comparer des number et des string ?

 

Ligne 28 ne devrait-elle pas être ?

then status_volets="Fermés";
  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

essaye un peu avec une entête comme ceci:

 

--[[
%% properties
%% globals
PRESENCE
GLOBALE_FERMETURE
--]]

et je pense aussi qu'il y a trop de tonumber et que tu pourrais les supprimer

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Bien vu Messieurs ;)

 

Bon, le if ... tonumber() == tostring()

n'était clairement pas bon...

 

Pour les tonumber, je les ai mis car je me suis aperçu que si je ne le mettais pas, ça ne fonctionnais pas (dans mon autre scène qui teste ces variables globales dans une boucle while...)

 

J'ai donc modifié le code :

--[[
%% properties
%% globals
PRESENCE
GLOBALE_FERMETURE
--]]

local jour = os.date("%Y:%M:%D");
local heure = os.date("%H:%M");
local status = "";
local status_volets = "";

local startSource = fibaro:getSourceTrigger();
if (
    if ( fibaro:getGlobalValue("PRESENCE") == tonumber("1"))
        then status="Présent";
    elseif ( fibaro:getGlobalValue("PRESENCE") == == tonumber("2"))
        then status="Absent";
    elseif ( fibaro:getGlobalValue("PRESENCE") == tonumber("3"))
        then status="Repos";
    else status="unknown";
    end

    if ( tostring(fibaro:getGlobalValue("GLOBALE_FERMETURE")) == tostring("ouverts"))
        then status_volets="Ouverts";
    elseif ( tostring(fibaro:getGlobalValue("GLOBALE_FERMETURE")) == tostring("fermes"))
        then status_volets="Fermés";
    end
    )
or
startSource["type"] == "other"
)
then
    fibaro:debug("------------------------------------------------------");
    fibaro:debug("Statut de présence : "..status);
    fibaro:debug("Statut des volets : "..status_volets);
    fibaro:debug("------------------------------------------------------");
end

 

J'ai quand même une erreur :

[ERROR] 10:51:20: line 15: unexpected symbol near 'if'

 

Et là , je ne vois pas

Partager ce message


Lien à poster
Partager sur d’autres sites

en fait, j'ai remarqué que chez moi le debug se référait toujours àla ligne qui précède celle qu'il mentionne.

Donc chez toi, ligne 14. Je crois qu'il manque une (, car celle ) de la ligne 32 n'a pas de correspondant (, qui je crois devrait être en ligne 14

Partager ce message


Lien à poster
Partager sur d’autres sites

×