Aller au contenu

[Résolu] Créer variable d'état en fonction du capteur qui a détecté un mouvement en dernier


J3R3M

Messages recommandés

Bonjour à tous,

 

Pour les nombreux membres qui ne me connaissent pas, je m'appelle Jérémy et je suis de plus en plus actif sur ce forum après m'être lancé dans la domotique via l'achat de plusieurs modules Fibaro et d'un HC2.

J'essaie de me documenter un maximum afin d'être le plus indépendant possible, mais il est indéniable que, pour le moment, je ne m'y connaisse vraiment pas assez pour ne serait-ce que comprendre un tutoriel qui vous semble très basique. Je pose donc beaucoup de questions et apprend sur le tas pour le moment et je vous remercie d'avance de votre aide et surtout de votre patience !

 

Venons-en aux faits. Derrière le titre de cette publication qui peut paraître un peu terrifiant, mon but est simple (du moins à comprendre).

 

Je dispose d'un détecteur de mouvement par pièce de mon domicile et, en fonction de ceux-ci, je voudrais pouvoir être "localisé" par la HC2 et, par la suite, pouvoir créer des scènes via ces "localisations"

 

Afin que ça soit plus clair, je vous propose trois exemples :

- Si, parmi tous les capteurs de mon domicile, le dernier à avoir détecté un mouvement est celui de la chambre et que ça n'a pas changé depuis 15mn, je suis couché

- Si, parmi tous les capteurs de mon domicile, le dernier à avoir détecté un mouvement est celui de l'entrée et que ça n'a pas changé depuis 15mn, je suis sorti

- Si, parmi tous les capteurs de mon domicile, le dernier à avoir détecté un mouvement est celui des toilettes et que ça n'a pas changé depuis 15mn, je suis constipé

 

 

En ce qui concerne le dernier exemple, cela n'aurait pas grand intérêt pour la domotique...

Mais pour les deux premiers exemples, je pensais à la création d'une variable qui pourrait être rappelée lors de la création de scènes.

Par exemple, une variable DODO et une autre DEHORS dont les résultats pourraient être 0 ou 1, ou YES ou NO, je ne sais pas quelles sont les possibilités d'ailleurs.

 

Concrètement, je voudrais pouvoir automatiser une extinction de mes éclairages et de mes enceintes lorsque je pars de chez moi et automatiser d'autres choses si je me suis endormi...

 

J'espère avoir été le plus clair possible. N'hésitez évidemment pas à me le faire savoir si ça ne devait pas être le cas et je me ferai une joie de tenter d'être davantage explicite.

 

Je vous remercie de m'avoir lu et vous remercie également par avance de vos réponses ! :)

Modifié par J3R3M
Mise en forme
Lien vers le commentaire
Partager sur d’autres sites

à froid comme ça, tu crées une scène qui analyse en boucle (toutes les minutes) le dateTime de la dernière modification de tes détecteurs.

Si la différence entre l’heure système (donc l’heure actualisée toutes les minutes) et le dateTime est > 15 min tu fais telle ou telle action.

 

http://www.fibarouk.co.uk/support/lua/library/fibarogetmodificationtime/

 

Ensuite tes variables globales DODO ou DEHORS sont de toute façon de type string, donc que tu mettes 0, 1, YES, NO, ne changera rien.

Mais la logique voudrait mettre 0 ou 1.

  • Upvote 1
Lien vers le commentaire
Partager sur d’autres sites

Bonjour à vous deux et merci de ces réponses !

 

Que ça soit une méthode ou l'autre, je ne saurai deviner quelle serait la meilleure, je ne saurai même pas comment la mettre en place puisque je suis encore bien trop débutant pour comprendre les démarches à effectuer pour l'une ou l'autre.

En effet, je ne maîtrise absolument pas le LUA et pour être honnête, je l'ai découvert il y a très peu de temps, en m'intéressant à la domotique...

Lien vers le commentaire
Partager sur d’autres sites

Il y a 10 heures, mprinfo a dit :

 

tu peux aussi utiliser les trigger qui vont déclencher une scène

 

j’y avais pensé, mais je vois pas comment l’exploiter.

il faudrait faire un sleep ou un timeout de 15 min !?

et après ? et que faire en cas de nouveau déclenchement ?

Lien vers le commentaire
Partager sur d’autres sites

tu peux tué la scène ou et utiliser le compteur de scène. le déclenchement sert a la première détection après dans la scène une boucle de 15 mn max qui va vérifié les déclenchements et lancé les actions. si rien ne ce passe après 15 mn la scène s’arrête 

Lien vers le commentaire
Partager sur d’autres sites

ah oui donc tu autorise do,c plusieurs instances de scènes ?

 

y a pas une fonction qui permet de démarrer une nouvelle instance de scène en tuant les précédente ?

je crois qu’on en a parlé y a pas si longtemps que ça ... mais je me souviens plus...

Lien vers le commentaire
Partager sur d’autres sites

AH voilà, j’ai retrouvé la « fonction » permettant de supprimer les instances en cours pour ne garder que seulement la nouvelle instance !

 

il faut ajouter dans l’entête de la scène :

 

%%killOtherInstances

 

Et oui du coup en effet ça peut être utile dans ce cas... - mais jamais testé !

Par contre ça me donne des idées ;) 

  • Upvote 1
Lien vers le commentaire
Partager sur d’autres sites

Je suis heureux de voir que ma question ait permis de découvrir de nouvelles perspectives ! :)

Cependant, moi qui commence seulement à utiliser les scènes en mode "Bloc Graphique", je dois avouer que vous m'avez perdu sur le coup.

Peut être sauriez-vous m'aider à retrouver ma route ? :D

Lien vers le commentaire
Partager sur d’autres sites

Il y a 6 heures, J3R3M a dit :

Peut être sauriez-vous m'aider à retrouver ma route

 

alors voilà un premier essai : (j’ai pas testé, y a certainement des erreurs...)

 

- il faut remplacer les XX par l’ID du détecteur de ta chambre (ou autre pièce).

- créer la Varaible Globale (VG) Dodo.

- ensuite créer une scène en lua et copier ce code.

- et tester...

 

 

--[[
%% killOtherInstances
%% properties
XX value
%% events
%% globals
--]]

--déclaration de variables locales
local IdDevice = XX
local Delai = 5 --délai (en minute) avant mise à 1 de la VG



--ne pas traiter le passage à 0 du détecteur (quand il détecte plus rien)
if tonumber(fibaro:getValue(IdDevice, "value") == 0 then fibaro:abort() end



print("Mouvement détecté")
print("Début du délai de "..Delai.." minutes")

--début du code qui sera executé en différé (après le délai)---------------------
setTimeout(function() 

	print("Délai terminé")
	print("Mise à 1 de la variable Dodo")
	fibaro:setGlobal("Dodo", 1) --mise à jour de la variable globale

end, Delai * 60 * 1000) -- *60*1000 car ce temps est millisecondes
--fin du code qui sera executé après le délai-------------------------------------



--ce code est exécuté avant le bloc précédent car pas de settimeout.
print("Valeur par defaut de la Variable Globale (0)")
fibaro:setGlobal("Dodo", 0) --mise à 0 (valeur par défaut) de la variable globale

normalement, lors d’iune détection, la scène se lance (les print dans le debug) te le confirmeront.

Si plus de détection pendant 5 minutes, la VG passe à 1.

Si nouvelle détection pendant les 5 minutes, on recommence tout le cycle.

Ainsi de suite.

Attention à ce que le paramètre du détecteur (le 6 de mémoire), ne soit pas supérieure au délai dans le script !

Lien vers le commentaire
Partager sur d’autres sites

Non jjacques68 ça ne produira pas le résultat escompté. Il faut tester le changement d'état du capteur de mouvement.

Retour aux fondamentaux comme on dit dans le sport ! :2:

https://www.domotique-fibaro.fr/topic/4933-settimeout/#comment-74451

 

Lien vers le commentaire
Partager sur d’autres sites

Perso, je ferais quelques chose de plus basique, soit d'aller vérifier toutes les X minutes le derniers détecteurs qui a été activé.

 

Soit :

 

--[[
%% autostart
]]--

local duree_max = 15 -- 15 minutes
local duree_refresh = 5 -- toutes les 5 minutes

local ids = {53, 48, 127} -- liste des id que l on souhaite controler

function run()
  
   local detecteurs = {}
   -- On parcours les ids pour trouver les informations
   -- nécessaires : id, modificationtime, name
   for i = 1, #ids do
      local device = api.get("/devices/"..ids[i])
      table.insert(detecteurs, {id=device.id, last=device.properties.lastBreached, name=device.name})
   end
  
   -- On les tri par ordre du plus récent
   table.sort(detecteurs, function(a, b) return a.last > b.last end)
  
   -- Si le dernier détecteur a été déclenché il y a plus de 15 minutes
   local plusrecent = detecteurs[1]
   local ilya = math.floor((os.time() - plusrecent.last)/60)
   if (ilya >= duree_max) then
    	
      -- TON CODE ICI
      fibaro:debug("Dernier détection : " .. plusrecent.name .. " il y a " .. ilya .. " minutes")  
    
    end
   setTimeout(function() run() end, duree_refresh*60*1000)  
end

run()

 

  • Like 1
  • Upvote 2
Lien vers le commentaire
Partager sur d’autres sites

Je vous remercie de toutes ces réponses et du temps passé pour essayer de trouver une solution !

Steven, si je comprends bien ton code (ce qui est loin d'être certain !), là où tu marques "TON CODE ICI", il faudrait créer une succession de conditions de ce genre :
 

if (plusrecent == (id Dectecteur Entrée) ) then -- Modification Variable DEHORS

elseif (plusrecent == (id Detecteur Chambre) ) then -- Modification Variable DODO

elseif (plusrecent == (id Detecteur SdB) ) then -- Modification Variable DOUCHE

 

J'espère que la syntaxe n'est pas trop décousue, je me suis documenté il y a quelques instants sur le LUA afin d'être moins perdu :)

Au final, mis à part le lancement de scripts en fonction de si je suis couché ou parti, je pense utiliser ce type de script pour détecter si je suis sorti ou non d'une pièce (à condition que je sois seul chez moi à ce moment, détecté selon la variable MOI_SEUL) et ainsi éviter de me retrouver dans le noir à la fin d'une temporisation...

 

JJaques, j'attends ton précieux retour quant à ce que tu as chez toi :)

Modifié par J3R3M
Lien vers le commentaire
Partager sur d’autres sites

C'est bien cela. Hors que ce sera plusrecent.id au lieu de plusrecent:

 

if (plusrecent.id == (id Dectecteur Entrée) ) then -- Modification Variable DEHORS
   fibaro:setGlobal("DEHORS", 1)
elseif (plusrecent.id == (id Detecteur Chambre) ) then -- Modification Variable DODO
   fibaro:setGlobal("DODO", 1)
elseif (plusrecent.id == (id Detecteur SdB) ) then -- Modification Variable DOUCHE
   fibaro:setGlobal("DOUCHE", 1)
end

 

  • Upvote 1
Lien vers le commentaire
Partager sur d’autres sites

ah bien vu @Berale24, ça marche pas en effet. :) suis allé trop vite...

 

Le %%killOtherInstances c'est ok, mais il faut tester en le passage à un 1 du détecteur.

 

J'ai vérifié, et chez moi je procède en faite différemment, j'utilise une boucle :

while fibaro:getValue(xx, "value") == 1 do end

et la durée est gérée grâce au paramètre 6 du détecteur.

Donc quand le détecteur passe à 0, il sort de la boucle et exécute le code qui suivra.

Je teste bien le passage à 1 du détecteur au préalable.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à tous,

 

Je suis désolé de ne répondre que maintenant, je suis en déplacement depuis un petit moment et l'accès à ma HC2 est super long depuis l'extérieur. Débit pas top en UP !

 

Voici le script de Steven qui fonctionne parfaitement :

 

--[[
%% autostart
]]--

local duree_max = 15 -- 15 minutes
local duree_refresh = 5 -- toutes les 5 minutes

local ids = {1, 2} -- liste des id que l on souhaite controler

function run()
  
   local detecteurs = {}
   -- On parcourt les ids pour trouver les informations
   -- nécessaires : id, modificationtime, name
   for i = 1, #ids do
      local device = api.get("/devices/"..ids[i])
      table.insert(detecteurs, {id=device.id, last=device.properties.lastBreached, name=device.name})
   end
  
   -- On les trie par ordre du plus récent
   table.sort(detecteurs, function(a, b) return a.last > b.last end)
  
   -- Si le dernier détecteur a été déclenché il y a plus de 15 minutes
   local plusrecent = detecteurs[1]
   local ilya = math.floor((os.time() - plusrecent.last)/60)
   if (ilya >= duree_max) then
    	
        if (plusrecent.id == 1) then -- Modification Variable DEHORS
     	fibaro:setGlobal("MOI_DEHORS", 1)
      	fibaro:setGlobal("MOI_DODO", 0)
 		elseif (plusrecent.id == 2) then -- Modification Variable DODO
        fibaro:setGlobal("MOI_DEHORS", 0)
     	fibaro:setGlobal("MOI_DODO", 1)
 		end
      fibaro:debug("Dernière détection : " .. plusrecent.name .. " il y a " .. ilya .. " minutes")  
    
    end
   setTimeout(function() run() end, duree_refresh*60*1000)  
end

run()

 

Mais, si j'ai bien saisi vos propos précédents, ce script ne serait donc pas optimisé pour agir dès le déclenchement d'un capteur puisqu'il faudrait qu'il vérifie l'état de chaque capteur chaque seconde.

 

mprinfo avait donc évoqué l'utilisation des triggers des détecteurs afin de changer les valeurs des variables.

Est-ce de cette manière que tu as fait chez toi jjacques68 ?

Modifié par J3R3M
Lien vers le commentaire
Partager sur d’autres sites

Il y a différents moyens pour optimiser ce genre de problématique. Perso, je ne pense pas que l'optimisation à outrance soit un gain réel. 

 

Le %% killOtherInstances ne peut pas être utilisé avec un détecteur car lorsque le détecteur repasse en mode de sommeil (x secondes après la détection), il va déclenché cette même scène et donc tuer la précédente qui faisait tranquillement son travail.

 

Il y a d'autre alternative mais la meilleures reste toujours : celle qui fonctionne.

 

Mais il y a des bonnes idées dans tous ces message ... perso, je ne connaissais pas le %% killOtherInstances.

Il n'est pas très judicieux d'avoir une scène qui tourne toutes les 5mn pour rien s'il n'y a pas de détection donc l'usage des triggers serait un plus.

 

Peut-être que le mieux serait d'avoir une scène qui se réveille au changement d'état d'un détecteur et qu'elle dorme 15mn. A la fin des 15mn, elle vérifie qu'elle est bien la dernière à avoir été activé par rapport au autres détecteurs. Cela serait le plus optimisé, à mon avis, mais après cela dépend du nombre de détection et détecteurs à gérer dans une journée.

 

Voilà donc mon avis personnelle sur la question.

 

 

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Le ‎07‎/‎11‎/‎2017 à 19:03, J3R3M a dit :

Est-ce de cette manière que tu as fait chez toi jjacques68 ?

 

désolé pour ma réponse tardive...

Dans mon cas, je n'utilise pas les FGSM pour les mêmes objectif que toi.

Mais voici un exemple de la scène plutôt simple, qui me gère mes éclairage avec les PIR :

--[[
%% properties
378 value
322 value
313 value
298 value
391 value
428 value
443 value
%% events
%% globals
--]]

--[[
- scène pour gérer tous les éclairages intérieurs par PIR
- Je ne fais pas d'association directe entre les modules
- La marche forcée se gère grâce au VD Mode Eclairage 383
- Ne tient pas compte du capteur Philio PSP05 car trop différent
  (donc scène a part = 210)
- Doit faire la différence entre les type d'actionneur (FGS ou  IPX)
--]]

local Device = {
--ID_PIR = {ID_actionneur, VG_Mode éclairage}
  [378] = {ID = 374, VG = "ModeEclDebarras"},
  [322] = {ID = 318, VG = "ModeEclWc"},
  [313] = {ID = 311, VG = "ModeEclSdB"},
  [298] = {ID = 296, VG = "ModeEclEscalier"},
  [391] = {ID = 405, VG = "ModeEclChaufferie"},
  [428] = {ID = 420, VG = "ModeEclGarage"},
  [443] = {ID = 441, VG = "ModeEclBuanderie"},
}

local Trigger = fibaro:getSourceTrigger()

--si mode manu (VD 383) on sort.
if tonumber(fibaro:getGlobalValue(Device[Trigger.deviceID].VG)) == 0 then fibaro:abort() end

--si PIR = ON
if tonumber(fibaro:getValue(Trigger.deviceID, "value")) == 1 then  
  --actionneur = FGS
  if fibaro:getType(Device[Trigger.deviceID].ID) == "com.fibaro.binarySwitch" 
    or fibaro:getType(Device[Trigger.deviceID].ID) == "com.fibaro.FGD212" then      
      fibaro:call(Device[Trigger.deviceID].ID, "turnOn")
      --tempo
      while tonumber(fibaro:getValue(Trigger.deviceID, "value")) == 1 do end 
      fibaro:call(Device[Trigger.deviceID].ID, "turnOff")
  
  --actionneur = IPX
  elseif fibaro:getType(Device[Trigger.deviceID].ID) == "virtual_device" then  	  
      fibaro:call(Device[Trigger.deviceID].ID, "pressButton", 1)
      --tempo
  	  while tonumber(fibaro:getValue(Trigger.deviceID, "value")) == 1 do end
  	  fibaro:call(Device[Trigger.deviceID].ID, "pressButton", 2)
  
  --si pas le bon actionneur
  else
    print("Type Device = "..fibaro:getType(Device[Trigger.deviceID].ID))
  end    
end

elle marche super bien. Le seul reproche que je puisse faire est que je constate une petite seconde de temps de réaction antre la détection du PIR et l'allumage de la lumière. :( 

Je rappelle que la durée d'allumage est donc gérée par le paramètre 6 des PIR.

 

 

@Steven, j'ai découvert le %%killOtherInstances cet été sur le fofo :) , mais j'ai pas encore trouvé d'utilité. Il y en aurait certainement, mais on est tellement habitué à fonctionner sans que c'est pas du tout une fonction naturelle ;) 

 

Il y a 12 heures, Steven a dit :

Le %% killOtherInstances ne peut pas être utilisé avec un détecteur car lorsque le détecteur repasse en mode de sommeil (x secondes après la détection), il va déclenché cette même scène et donc tuer la précédente qui faisait tranquillement son travail.

 

tout à fait, je m'en suis rendu compte pendant les tests :) 

Lien vers le commentaire
Partager sur d’autres sites

Le 08/11/2017 à 11:00, Steven a dit :

Il y a différents moyens pour optimiser ce genre de problématique. Perso, je ne pense pas que l'optimisation à outrance soit un gain réel.

 

Je suis totalement d'accord, mais il doit y avoir un juste milieu entre une scène qui risque de tourner pour rien 95% du temps et un script infaisable :)

Et d'ailleurs, il semblerait que tu aies toi-même trouvé ce fameux compromis, cette fameuse optimisation :

 

Le 08/11/2017 à 11:00, Steven a dit :

Peut-être que le mieux serait d'avoir une scène qui se réveille au changement d'état d'un détecteur et qu'elle dorme 15mn. A la fin des 15mn, elle vérifie qu'elle est bien la dernière à avoir été activé par rapport au autres détecteurs. Cela serait le plus optimisé, à mon avis, mais après cela dépend du nombre de détection et détecteurs à gérer dans une journée.

 

Cela me semble parfait !
J'ai essayé de modifier le script que tu avais initialement posté dans le but de l'optimiser ainsi.

Je me suis renseigné sur la commande fibaro:sleep(), mais j'ai l'impression qu'il faille complètement recréer un autre script.

 

Je suis sincèrement désolé de ne pas être capable de mettre en place quelque chose qui a l'air de vous sembler évident.

Je comprends très bien ce que tu expliques, c'est totalement logique d'ailleurs, mais je suis bloqué dès que j'essaie de transcrire tes propos en script.

Peux-tu éventuellement me mettre sur la voie en me donnant des liens et/ou des portions de scripts qui me permettraient d'avancer ?

 

Actuellement, je n'ai que 3 détecteurs de mouvements (3 FGSM).

Par la suite, j'espère en avoir 5 de plus. En effet, via d'autres sujets postés sur ce forum, j'essaie en parallèle de voir pour que mes 3 Hue Motion Sensor et mes 2 caméras AXIS puissent également être intégrés dans la HC2 comme détecteurs de mouvements (sous forme de VD via l'API des produits je suppose ?).

 

Il y a 14 heures, jjacques68 a dit :

désolé pour ma réponse tardive...

 

Jjacques, tu n'as absolument pas à être désolé.

C'est déjà très gentil de la part de chaque personne de prendre de son temps pour m'aider dans mes débuts ! :)

Merci d'ailleurs à tous de continuer à suivre l'évolution de ce sujet !

 

Concernant ton code, je suis en train de me documenter pour essayer de le comprendre un maximum !

En ce qui concerne les FGSM, sache que j'ai également cette seconde de latence et ce, malgré des scènes aussi simples que "SI MOUVEMENT ALORS ALLUMER ET ETEINDRE 120s PLUS TARD" (effectuées en mode bloc graphique) :/

Modifié par J3R3M
Lien vers le commentaire
Partager sur d’autres sites

Non testé

 

Si détection, on démarre une attente de X minutes. A la fin de cette attente, si on est toujours le dernier détecteur à avoir été activé alors on modifier les variables globales en conséquence.

 

Je pense difficile de faire plus optimisé.

 

Ce scénario ne peut être exécuté que par le déclenchement d'un détecteur. L'appui sur le bouton [Play] du scénario va le faire planté

 

--[[
%% properties
1 value
2 value
]]--

local duree_attente = 15 -- 15 minutes

local detecteurs = {
  -- [<id_detecteur>], <variable globale>
  [1] = "MOI_DEHORS",
  [2] = "MOI_DODO"
}

-- ---------------------------------------
-- Est-il bien le dernier déclenché
-- ---------------------------------------
function isLast(id) 
  local lastBreached = tonumber(fibaro:getValue(id, "lastBreached"))
  for k, _ in pairs(detecteurs) do
    if (lastBreached < tonumber(fibaro:getValue(k, "lastBreached"))) then
      return false
    end
  end
  return true
end

-- ---------------------------------------
-- Modifie les variables globales
-- ---------------------------------------
function setGlobal(id)
  for _, v in pairs(detecteurs) do fibaro:setGlobal(v, "0") end
  fibaro:setGlobal(detecteurs[id], "1")
end

-- ------- Programme principal -----------
local id_declencheur = tonumber(fibaro:getSourceTrigger().deviceID)
if (fibaro:getValue(id_declencheur, "value") ~= "0") then
  setTimeout(function() 
      if (isLast(id_declencheur)) then setGlobal(id_declencheur) end
  end, duree_attente*60*1000)
end

 

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Je reviens après avoir essayé le script et il semblerait qu'il y ait une erreur.

 

Citation

[DEBUG] 00:03:53: line 115: attempt to concatenate local 'deviceId' (a nil value)

 

Ce que je n'arrive pas à saisir puisqu'il y a largement moins de 115 lignes dans le script que tu as fait :D

Lien vers le commentaire
Partager sur d’autres sites

×
×
  • Créer...