Aller au contenu

[Résolu] [LUA] Effectuer une action répétée sur un bouton ou vérifier avant afin qu'elle ne soit pas répétée?


Messages recommandés

Posté(e) (modifié)

Hello,

 

Je me pose une petite question concernant la programmation LUA sur la HC2.

Je sais que la formulation du titre de ce message peut paraître décousue, mais je vais essayer de l'expliciter, notamment par un ou deux exemples.

 

Je cherche à savoir comment vous organisez vos actions sur vos HC2. Le but étant de savoir ce qui la sollicite le moins.

À savoir, dans des situations particulières, est-ce qu'il est préférable de reproduire la même action ? Ou bien, est-il plus optimisé de d'abord vérifier un état avant d'effectuer une action?

 

Quelques exemples :

Allumage automatique de la lumière

Celle-ci est déjà allumée. Lorsqu'un nouveau mouvement est détecté dans la pièce, vous renvoyez l'ordre d'allumer (Device ou Virtual Device) ou vous mettez en place une condition qui vérifie si la lumière est déjà allumée?

Variable Globale de détection de téléphone

Votre téléphone a été détecté par un script bash. Celui-ci appuie sur un bouton de VD toutes les 10s. Même question, est-il préférable de le laisser agir ou de mettre en place une condition pour vérifier avant la modification?

Enregistrement automatique des caméras

Les caméras enregistrent automatiquement lorsqu'un mouvement est détecté et que personne n'est reconnu au domicile. On appuie sur le bouton REC à chaque nouveau mouvement ou on vérifie avant si un enregistrement est déjà en cours?

 

De mon côté, j'effectue à chaque fois une vérification avant de modifer un état ou d'appuyer sur un bouton.

Cependant, dans quelques cas plus complexes, la vérification prendra beaucoup de lignes de code, là où l'envoi de la commande (donc potentiellement répétée très régulièrement) n'en prendra qu'une.

J'ai tendance à penser que l'appui sur un bouton de VD (par exemple) toutes les minutes sollicitera moins notre HC2 que plusieurs vérifications (dans plusieurs Variables Globales, plusieurs VD).

 

Suis-je dans le faux?

Comment faites-vous de votre côté?

Modifié par J3R3M
Posté(e)

je dirais ça dépends du type d'action :

  1. pour les VG, je ferais le test, car sinon il réécrit pour rien la même valeur sur la mémoire interne, et je pense qu'on pourrait user prématurément (à confirmer par les vrais pros)
  2. pour les requêtes http, je dirais que lire une valeur est plus rapide que l'écrire
  3. pour les FGS, etc, j'ai lu ici quelque part (@benjinet ?) qu'ils avaient mis en place dans les relais Fibaro, un système pour qu'il ne se ferme pas si'il est déjà fermé, car sinon il s'userait inutilement => pas de test
Posté(e) (modifié)
il y a 9 minutes, jojo a dit :

pour les VG, je ferais le test, car sinon il réécrit pour rien la même valeur sur la mémoire interne, et je pense qu'on pourrait user prématurément (à confirmer par les vrais pros)

Les VGs ne seraient-elles pas auto-protégées de fausses modifications ?

En fait, en faisant des essais, j'ai pu me rendre compte que la valeur renvoyée par le fibaro:GetGlobalModificationTime() d'une VG ne variait pas lorsqu'on renvoyait exactement même valeur dans la Variable Globale, même plusieurs jours après.

Modifié par J3R3M
Posté(e)
Il y a 11 heures, J3R3M a dit :

En fait, en faisant des essais, j'ai pu me rendre compte que la valeur renvoyée par le fibaro:GetGlobalModificationTime() d'une VG ne variait pas lorsqu'on renvoyait exactement même valeur dans la Variable Globale, même plusieurs jours après.

Bonjour,

 

Je n'avais jamais fait attention, peut-etre que oui dans ce cas alors.

 

Si on parle de PERFS, de mon point de vue de non developpeur, je trouve plus cohérent de tester afin d'envoyer une trame inutile. En terme de perf, la lecture est moins gourmande que l'ecriture.

Pour moi, ce sont de BONNES PRATIQUES, je trouve cela plus propre. LA méthode "J'ALLUME" bien que ce soit déjà ALLUME est un peu vrute de decoffrage non ?

Posté(e)

Pour ce qui concerne des relais et des VG, le test est selon moi inutile car la box le fait systématiquement.

 

La HC2 vérifie systématiquement l'état d'un module et d'une VG avant de changer son état. Donc pour moi, il est quasiment inutile d'aller systématiquement l'interroger pour connaitre son état avant d'envoyer une demande.

 

Si tu allume un module déjà allumé ... la box n'envoi pas de trame z-wave, ce qui signifie qu'elle a vérifié l'état du module par elle-même.

Si tu change la valeur d'une VG par la même valeur, la box ne change pas la VG, elle ne met pas la date à jour et n'envoi pas les "triggers" pour enclencher les scénarios.

 

Bref, elle fait déjà le travail par elle-même. Donc fréquemment, tu ferras une double vérification inutile et plus coûteux.

 

Après ... c'est une HC2, elle est largement capable de supporter tout cela :P

 

 

 

 

 

 

 

 

  • Like 1
  • Thanks 1
Posté(e)

D'un point de vue humain, je comprends le raisonnement de @pepite. Si on voit que la lampe est éteinte, on l'allume sinon on ne fait rien. 

D'un point de vue logique ... on s'en fiche de son état, on veux qu'elle soit allumée .. point final. Donc on laisse la box se débrouiller par elle-même.

 

Après tout, à chacun son boulot ;)

  • Haha 1
Posté(e)

J'ai encore, par curiosité, vérifier mon GEA. A aucun moment, je vérifie l'état d'un module avant d'effectuer une action dessus. Résultat, 0 plantée depuis des années.

 

Le seul moment ou je vérifie est si je veux que le module s'éteigne après X temps, du style

 

GEA.add( 128, 300, "Allumé depuis 300sec", {"turnOff"})

 

Car dans ce cas, je n'ai pas le choix.

Posté(e)

punaise !!  je viens de lire le post, moi depuis toujours, pour les relais, je test son état avant d’actionner...

 

si j’avais su que c’était pas utile... 

 

c’est étrange par ce qu’il me semble que pour les relais des volets, j’entendais un clic quand meme... pour cela que je testais avant

Du style quand on veut fermer un volet qui est déjà fermé... faut que je re essaye...

  • Like 1
Posté(e)

Merci de ces précisions @Steven!

Je me permets de demander quelques précisions supplémentaires.

 

Concernant les scènes...

Est-il mieux de minimiser le nombre de scènes ou de bien distinguer chaque action?

Par exemple, à l'heure actuelle, une seule scène gère toutes les pièces de chez moi, que ça concerne la lumière, les enceintes, les Wall Plugs, la gestion des caméras, l'alarme... Serait-il préférable d'avoir une scène par type d'action?

Posté(e)

Pour moi, cela dépends principalement du nombres d'interactions qu'on les modules entre eux. Mais cela uniquement car je n'aime pas les variables globales.

Posté(e) (modifié)

Dans mon cas, chaque détection de mouvement mène sur des actions différentes pour chaque type de module, mais elles ne sont pas liées par autre chose que le déclencheur.

L'allumage ou non de la lumière est totalement indépendant de l'augmentation du volume des enceintes de la pièce par exemple. Tout comme l'allumage ou non d'un Wall Plug. Il n'y a vraiment rien de lié.

J'ai préféré utiliser une seule scène, qui peut parfois mettre un peu de temps à s'exécuter complètement, en me disant que ça serait plus simple à gérer par la HC2 que 4-5 scènes qui pouvaient démarrer simultanément pour chaque nouveau mouvement. Mais peut-être suis-je dans le faux?

 

Concernant les Variables Globales, j'y ai, peut être à tort, stocké la totalité des informations nécessaires pour mes pièces. De l'ID des modules la concernant jusqu'aux réglages des différentes valeurs en fonction du moment de la journée.

Ça impose de rechercher dans cette VG pour chacune de mes scènes, mais ça limite à l'utilisation d'une seule scène pour toutes les pièces.

Modifié par J3R3M
Posté(e)

Pour mon, un VG n'a de l'intérêt que pour échanger de l'information entre scènes/VD, ... moins on y fait appel plus le scénario est performant.

 

Stocker un VG signifie stocker des informations dans la base de données de la HC2. Donc stocker des données déjà présentent dans la base est, pour moi, inutile. Par exemple, les ID des modules d'une pièce sont déjà dans la base.

Si la base de données de la HC2 est bien indexée, aller lire une VG devrait revenir au même que de demander la liste des modules d'une pièce. Mais je ne connais pas la structure de la base.

 

Pour ce qui est des scénarios, je fais un peu comme toi. C'est à dire, regarder les déclencheurs et regrouper les actions par déclencheur. Mais cela reste un choix purement personnel, je ne pense pas qu'un solution soit meilleur qu'une autre. Est-ce mieux de déclencher 4-5 petites scènes bien optimisées ou 1 grosse scène ? Perso, je pense qu'il faut se baser uniquement sur "ses préférences" et "sa propre organisation". La HC2 est capable de supporter beaucoup de chose et se contraindre à la soulager est presque ridicule.

 

Donc, pour résumé, je dirais que tu as raison car tu y vas selon ton feeling.

  • Like 1
Posté(e)

Merci encore de ces précisions.

Suite à ton post, j'ai fait quelques recherches et j'ai pu découvrir que bien des fonction de l'API Fibaro m'avaient échappées.

 

Une fois de plus, une nouvelle interrogation : niveau rapidité d'éxecution et performance d'un script.

Actuellement, les IDs de tous mes détecteurs de mouvements sont effectivement stockées dans une VG (tableau json, indexés par pièce).

Malgré la redondance de l'info des IDs dans la base de données, j'aurais tendance à penser qu'un script s'exécutera plus rapidement en parcourant des IDs connus, plutôt qu'en reformant un préalable un tableau avec les IDs qui nous intéressent avant de les traiter.

 

Je me relis et je me dis que ça peut paraître confus, voici deux exemples rapides :

-- Cas 1 : IDs déjà référencés dans un tableau
-- Dans mon cas, la clé est le nom que j'ai donné à ma pièce

local piece = "SALON";

local t = {};
t["SALON"] = {3,19};
t["CUISINE"] = {7,45};

tablePiece = t[piece];

for k,v in pairs (tablePiece) do
  fibaro:debug(v);
end

-- Cas 2 : Recherche dans la base de données de la HC2
-- Donc utilisation obligatoire de l'ID de la pièce, puisqu'on a besoin de l'ID d'un module de la pièce pour fibaro:getRoomName(), n'est-ce pas?

local PieceId = 6

local devices = fibaro:getDevicesId({roomID=PieceId,baseType="com.fibaro.FGMS001",visible=true})
for
 k,v in ipairs(devices)
 do
  fibaro:debug(v);
end

 

Suis-je une fois de plus dans le faux?

Posté(e)

Si ton tableau est connu et que tu n'as pas besoin de json, les performances sont excellentes comparées à une recherche en base. Et dans ce cas, il n'y a même pas photo.

 

En revanche, si tu dois stocker ton tableau dans une VG avec du json, le gain me semble beaucoup moins significatif.

Posté(e) (modifié)

En fait, voici comment sont gérées les informations de mes pièces, avec les explications en commentaire.

Est-ce que parcourir cette table (qui est assez conséquente, je le conçois) causerait des pertes de performance dans mes scripts?

Puisque j'utilise les informations de la base, c'est certain, mais je les joins à d'autres paramètres que je crée dans ce tableau.

(Oui, j'ai les explications en commentaire, s'il m'arrivait quelque chose, j'aimerais bien que ça soit compréhensible :P)

 

--id =				ID de la pièce correspond à l'id du bouton du VD Pièce Active
--Code =			Code de la pièce. Doit être similaire à la clé du tableau principal
--Nom =				Nom de la pièce avec majuscule et accents (pour utilisation propre dans SMS par ex)
--Article =			Article du nom de la pièce (ex : "l'" pour "entrée")
--Detect =			Table des id des détecteurs Fibaro. Si cam, mettre "cam"
--LumMini = 		À partir de quel seuil de luminosité (lux) la lumière doit-elle s'allumer. nil si uniquement cam
--LumMax =			Table des luminosités maximales détectées par chaque détecteur lorsque toutes les lampes gérées sont allumées à 100%. Le but étant de se baser sur ses valeurs pour déterminer si une autre source de lumière est présente.
--Passage =			0/1 - Pièce de passage ou non ? Par exemple, un couloir est un lieu de passage.
--TpsActive	=		Temps maxi durant lequel la pièce restera considérée comme active sans le moindre mouvement
--JourNuit = 		0/1 - Gestion automatique de l'allumage de la pièce (basé sur les heures de levés et couchés du soleil). Utile lorsque seule une cam détecte les mouvements de la pièce
--HueGroup =		Table des Ids des VDs Groupe Hue de la pièce
--HueList =			Table des Ids des VDs des ampoules Hues utilisées dans la pièce
--HueType =			Table des types des lampes Hues précédemment déclarées
------------------------------------------------------------------------------
-- Pour les réglages Hue suivants, si une seule valeur est définie, on utilisera
-- le(s) groupe(s) défini(s) ci-dessus dans HueGroup
-- Toutes les valeurs sont stockés dans une table, pour chaque réglage
-- Valeur de 0 à 100%, dans le même ordre que les lampes ont été définies dans HueList
------------------------------------------------------------------------------
--HuePowerDodo =	Table des valeurs lorsque la pièce est en mode DODO
--HuePowerAM =		Table des valeurs lorsque Moment = Matinée
--HuePowerMidi =	Table des valeurs lorsque Moment = Midi
--HuePowerPM =		Table des valeurs lorsque Moment = Après-Midi
--HuePowerSoir =	Table des valeurs lorsque Moment = Soirée
--HuePowerNuit =	Table des valeurs lorsque Moment = Nuit
--SonosId =			ID du VD SONOS de la pièce
--SonosVMax =		Table contenant les volumes maxi autorisés pour l'enceinte, en fonction du moment de la journée
--SonosV =			Table contenant les volumes auxquels seront montées la SONOS en fonction du moment de la journée
--VoletsR =			IDs des Roller Shutter de la pièce (pour gestion auto)
--Chambre =			La pièce est-elle une chambre ?
------------------------------------------------------------------------------
---------- Les valeurs suivantes sont gérées par les scènes et vd ------------
------------------------------------------------------------------------------
--Dodo = 			Mode DODO de la pièce 0 ou 1
--DodoMT =			Dodo Modification Time
--Mise =			Mise = 0/1 - Si Mise = 1, gestion manuelle des éclairages de la pièce
--PowerMode =		Valeur ou Auto géré via le VD Puissance Lights
--LastHueValue =	Dernières valeurs (Puissance) des Hues de la pièce avant extinction. Ces valeurs seront rappelées en cas de nouveau mouvement dans l'heure.
--LastSonosLvl =	Dernier niveau de puissance des enceintes de la pièce
--LastMove =		Dernier mouvement détecté dans la pièce
--LastLightsOn =	Dernier allumage automatique effectué dans la pièce
--LastLightsOff =	Dernière extinction automatique effectuée dans la pièce
------------------------------------------------------------------------------

-------- Récupération des valeurs gérées automatiquement --------
local table = json.decode(fibaro:getGlobalValue("T_INFOS_PIECES"));

-------- Paramètres des Pièces -------
local pieces = {};

pieces["ENTREE"] = {
    id =			1,
    Code =			"ENTREE",
    Nom =			"Entrée",
    Article =		"l'",
    Detect =		{"cam"},
    LumMini = 		nil,
  	LumMax =		{nil},
  	Passage =		1,
  	TpsActive =		2,
	JourNuit = 		0,
    HueGroup =		{298},
    HueList =		{89,96,113,112},
   	HueType =		{"hcol", "hcol", "hcol", "hcol"},
    HuePowerDodo =	{5,0,0,5}, -- Une valeur = utilisation groupe
    HuePowerAM =	{30},
    HuePowerMidi =	{40},
    HuePowerPM =	{40},
    HuePowerSoir =	{40},
    HuePowerNuit =	{30},
    SonosId =		245,
 	SonosVMax =		{40,50,50,50,40},
  	SonosV =		{30,35,35,35,30},
  	VoletsR =		{nil},
  	Chambre =		0,
  	Dodo =			table["ENTREE"].Dodo,
  	DodoMT =		table["ENTREE"].DodoMT,
    Mise =			table["ENTREE"].Mise,
  	PowerMode =		table["ENTREE"].PowerMode,
    LastHueValue =	table["ENTREE"].LastHueValue,
	LastSonosLvl =	table["ENTREE"].LastSonosLvl,
    LastMove =		table["ENTREE"].LastMove,
    LastLightsOn =	table["ENTREE"].LastLightsOn,
  	LastLightsOff = table["ENTREE"].LastLightsOff
};

pieces["SDB"] = {
    id =			3,
    Code =			"SDB",
    Nom =			"Salle de Bain",
  	Article =		"la ",
    Detect =		{220,261},
    LumMini = 		4,
  	LumMax =		{219,5},
  	Passage =		0,
  	TpsActive =		2,
    JourNuit = 		0,
    HueGroup =		{301},
    HueList =		{93},
   	HueType =		{"hcol"},
    HuePowerDodo =	{5}, -- Une valeur = utilisation groupe
    HuePowerAM =	{100},
    HuePowerMidi =	{100},
    HuePowerPM =	{100},
    HuePowerSoir =	{100},
    HuePowerNuit =	{100},
    SonosId =		244,
 	SonosVMax =		{90,100,100,100,90},
  	SonosV =		{30,35,35,35,30},
  	VoletsR =		{nil},
  	Chambre =		0,
  	Dodo =			table["SDB"].Dodo,
  	DodoMT =		table["SDB"].DodoMT,
    Mise =			table["SDB"].Mise,
  	PowerMode =		table["SDB"].PowerMode,
    LastHueValue =	table["SDB"].LastHueValue,
	LastSonosLvl =	table["SDB"].LastSonosLvl,
    LastMove =		table["SDB"].LastMove,
    LastLightsOn =	table["SDB"].LastLightsOn,
  	LastLightsOff = table["SDB"].LastLightsOff
};

fibaro:setGlobal("T_INFOS_PIECES", json.encode(pieces));
fibaro:debug("Informations enregistrées.");

 

Modifié par J3R3M
Posté(e)

Je continue de m'interroger...

Au niveau temps d'accès, est-il plus rapide de récupérer une information de la base de données que récupérer celle d'une VG?

Concrètement, pour connaître le timestamp du dernier mouvement d'une pièce, est-il plus rapide de l'enregistrer dans une VG (lors de la détection d'un mouvement) pour la récupérer directement ensuite ou est-il préférable de récupérer l'information LastBreached d'un module ?

 

Je parle bien évidemment en terme de rapidité d'accès, j'ai bien saisi que l'information était stockée dans la Base de Données dans tous les cas.

Posté(e)

Voici une petite scène pour toi :

--[[
%% properties
%% globals
--]]
 
local VG = "Chauffage"
local ID_LAST_BREACH = 53
local NB_ITERATION = 1000

-- Affiche dans la console ---
function log(name, start)
  	if (start) then
		fibaro:debug("<span style=\"font-family:monospace; white-space:pre; clear:both; float:right\">  "..name .. " " .. (os.time()-start) .. "s</span>")
	else
		fibaro:debug("<span style=\"font-family:monospace; white-space:pre; clear:both; float:right\">  "..name .. "</span>")
    end
end
 
-- Execution des fonctions ---
function execute(name, func)
  if (not pcall(function() 
        local start = os.time()
        for i= 1,NB_ITERATION do
          func()
        end
        log(name, start)
    	end)) then
  	fibaro:debug("ERROR : " .. name)
  end
end  
 
log("Test de performance")
log("----------------------------------------------")
log("")
 
-- Tests ---
execute("getLastBreach :", function() local m = fibaro:getValue(ID_LAST_BREACH, "lastBreached") end)
execute("getVG         :", function() local v,m = fibaro:getGlobal(VG) end)
 
log("")
log("----------------------------------------------")
log("ALL DONE")

Tu constateras que l'appel à la VG est légèrement plus rapide que de remonter le "lastBreached" d'un module. Test effectué sur 10'000 itérations.

 

[DEBUG] 09:30:13:   Test de performance
[DEBUG] 09:30:13:   ----------------------------------------------
[DEBUG] 09:30:13:   
[DEBUG] 09:30:45:   getLastBreach : 32s
[DEBUG] 09:31:14:   getVG         : 29s
[DEBUG] 09:31:14:   
[DEBUG] 09:31:14:   ----------------------------------------------
[DEBUG] 09:31:14:   ALL DONE

 

  • Like 1
  • Haha 1
×
×
  • Créer...