-
Compteur de contenus
25 989 -
Inscription
-
Dernière visite
-
Jours gagnés
1 280
Tout ce qui a été posté par Lazer
-
Bienvenue sur le forum
-
Oui, il vaut mieux prendre les bonnes habitudes dès le début A noter qu'un code optimisé tout court ça n'existe pas. On optimise dans un but précis, par exemple la performance CPU, ou bien l'empreinte mémoire. Et parfois, un code plus rapide consomme plus de RAM. Et/ou devient illisible. Je me souviens avoir appris à une époque étudiante qu'un appel de fonction c'est relativement long (ça consomme des cycles CPU), et un code rapide utilise le moins de fonctions possible.... donc on se retrouve avec des bouts de codes répétés plusieurs fois par ci par là dans le code... ça devient illisible et inmaintenable, mais c'est rapide. Ce qu'il faut trouver, c'est le juste milieu en fonction de l'effet recherché. Nous ça va, on veux juste faire des QA pour afficher 2 ou 3 informations dans un cadre domotique, ça reste simple. Tiens pendant que j'y pense en parlant performance et algorithme. J'ai mon QA Événements (partagé sur le forum) qui est le plus consommateur de RAM et de CPU de ma box, juste pour afficher les 25 derniers événements. Je sais pourquoi, il manipule de grosses tables, plusieurs centaines d'éléments, et le LUA n'est pas très bien optimisé à ce petit jeu là. Pendant mes vacances, il s'est emballé, a consommé jusqu'à 150 Mo de RAM (là où la plupart des QA consomment autour de 1 Mo seulement), et plusieurs pourcents de CPU. La box n'a pas crashé, pas rebooté, elle a tué le QA, et ne l'a pas redémarré (alors qu'il y a normalement un watchdog qui surveille le redémarrage des QA plantés). Bravo Fibaro pour la stabilité et la robustesse de la box Et pourtant dans ce QA, j'avais fait plein de micro-optimisations, notamment redéclarer toutes les variables et fonctions globales en local, etc.... mais c'était inutile en fin de compte, l'erreur était dans l'algorithme, la méthode que j'ai employé n'était pas la bonne (interrogation de l'API /events/history) J'ai commencé la réécriture en utilisant une autre méthode (/api/refreshStates), et les premiers résultats sont très encourageants, ça semble consommer moins de CPU et moins de RAM. Combo gagnant. Et cerise sur le gâteau, au lieu d'avoir un intervalle de rafraichissement de 60s, il est maintenant de 1s seulement ! Comme quoi, il faut parfois prendre le problème par un autre bout, et tout recommencer à zéro quand ça ne va pas.
-
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
Lazer a répondu à un(e) sujet de Lazer dans Quick App Developpeur
Tu calcules surement ta charge CPU de façon différente, moi je le fais avec DomoCharts, qui calcule ça en interne dans le QA avant d'exporter vers la DB. Du coup le pic CPU est visible uniquement à la fin du Freeze. La box figée, je l'ai déjà constaté, mais uniquement durant quelques secondes, lorsque j'ai trop d'onglets ouverts en même temps (plus de 4, ça empire si on ouvre 5 ou 6 onglets), et que j'enregistre un QA en cours d'édition. C'est ce qui m'avait fait dire à un moment que c'est le process d'écriture dans la DB qui fige les autres I/O, donc la box qui se met en attente de la disponibilité de la DB. Je ne sais pas si le freeze long a le même origine, les I/O. Il faudrait peut être vacciner la box pour réduire les risques de freeze long -
Dans l'ensemble, OUI.... mais je vais te reprendre sur 2 points : Dans l'exemple #2 : - "mavariable" a une portée locale (à tout le QA qui la contient), le code ne fait pas appel à la table "super-globale _G" durant son exécution => Il est incorrect de parler de portée, car mavariable est en réalité un élément de la table QuickApp. C'est là que le LUA est un peu étrange, et différent d'un vrai langage de programmation orienté objet (C++, Java, etc). QuickApp est donc une table, qui contient différents éléments : function, string, number, table, etc... La subtilité c'est que dans les fonctions, "self" pointe sur la table QuickApp elle-même, donc on a accès à tous les autres variables et fonctions de cette table, y compris notre fameuse mavariable. Du coup, par abus de langage, on dit que la portée de mavariable est celle de QuickApp, c'est à dire utilisable dans tous les fonctions membres de QuickApp. - performance exécution code théoriquement maxi => en fait non pas du tout, car pour aller chercher mavariable, le programme va devoir parcourir la table QuickApp.... donc la performance est plus ou moins similaire à celle d'une variable globale qu'on va rechercher dans _G. En fait, pour savoir lequel des 2 est plus rapide, il faut compter le nombre d'éléments dans les tables _G et QuickApp.... du coup, ben ça dépend de chaque programme. Après il ne faut pas non plus se focaliser sur cette histoire de performance d'accès aux variables, car c'est de l'ordre des nanosecondes (microseconde à tout casser), c'est inmesurable en pratique, sauf à avoir une boucle qui effectue un gros calcul et accès 1 millions de fois à la même variable. C'est sans commune mesure avec les performances d'accès à la base de données, qui se compte en millisecondes. Bien souvent quand on cherche à optimiser les performances d'un programme informatique, le gros des gains se fait sur l'algorithme utilisé, pas sur l'accès à telle ou telle variable. Et puis quand on cherche la performance maxi, on n'utilise pas du LUA (qui est déjà relativement rapide cela dit), mais plutôt du C... voire de l'assembleur. C'est un tout autre domaine, qu'on va rencontrer dans les moteurs de rendus 3D des jeux vidéos, le calcul scientifique, etc. Bref, l'important dans cette histoire, c'est la portée des variables, qu'on doit limiter à leur strict nécessaire, c'est une bonne pratique pour éviter les collisions de 2 variables qui porteraient le même nom dans 2 bouts de codes différents. C'est particulièrement vrai quand on réutilise des bouts de codes qu'on a déjà développé (sous forme de "librairie", que ça soit dans le même fichier LUA ou dans un autre fichier LUA du QuickApp)
-
En Z-Wave, un module peut être exclus par le contrôleur qui l'a inclus (donc la HCL dans ton cas), ou bien par n'importe quel autre contrôleur (donc la HC3L dans ton cas) La seule différence en pratique, c'est que : - si tu exclus avec la HCL, alors le module sera retiré de ton HCL - si tu exclus avec la HC3L, alors le module restera dans la HCL... Mais passera en nœud mort car la HCL ne pourra plus communiquer avec Personnellement j'ai tout exclu avec la HC3, car ça me permet de conserver les anciens modules sur la HC2, ainsi j'ai pu relever les anciens ID pour adapter mes scénarios, mais aussi retrouver les paramètres Z-Wave des modules, ou bien encore les icônes. Ensuite quand tu n'as plus besoin de la HCL, tu fais un recovery complet, ça fera le grand ménage.
-
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
Lazer a répondu à un(e) sujet de Lazer dans Quick App Developpeur
Et bien... suffisait d'en parler, ça vient de m'arriver, à 18h. Je me suis rendu compte que GEA n'avait pas exécuté une action à cette heure là (action simple, sans autre condition que l'heure) Je regarde la courbe CPU de DomoCharts, et je constaste un affreux pic à cette heure là.... donc forcément, GEA n'a pas pu exécuter l'action à l'heure dite. La solution de contournement, tant que Fibaro n'aura pas travaillé sur ce problème de freeze, c'est d'allonger les plages horaires "Time" qu'on utilise dans GEA.... Là où je suis inquiet, c'est que personne, à part toi et moi, ne semble avoir relevé ces freeze (faut dire que c'est pas évident à détecter).... et encore moins remonté sur le forum officiel, donc Fibaro n'est pas prêt de travailler sur ce sujet... D'ailleurs, c'est très étonnant que ça soit tous les jours à la même heure chez toi, car chez moi c'est assez rare. Plutôt tous les 15 jours, à des horaires variables. -
Ah voilà tu as retrouvé où on en a parlé il y a quelques temps Outre les problématiques de portée et de risque d'erreur de réutilisation, précisons, au sujet des performances, qu'il est plus rapide d'utiliser des variables locales que des variables globales (en LUA, ce n'est pas le cas avec d'autres langages) En effet, en LUA, accéder à une variable globale requiert de parcourir la table super-globale _G (une table qui contient toutes les variables globales, les fonctions, etc), ce qui prend des cycles CPU à chaque accès. Mais on parle là de micro-optimisations. Il n'y aura un gain sensible à ce niveau que pour un algorithme très lourd, avec une boucle qui effectue des millions d'accès à la même variable. Cela n'a rien à voir avec la différence de performance lors de l'accès à une variable persistante en DB, pour laquelle la différence de performance est considérable.
-
Attention de ne pas confondre : les variables LUA (qui existent dans le code LUA, qu'elles soient locales, globales, ou attribuées à un objet via self) => elles résident uniquement en RAM, elle sont créées à chaque démarrage du QuickApp, et perdues lors de son arrêt les variables persistantes de la box (globales, de QuickApp, ou de Scène) => elles sont stockées dans la DB, donc conservées à chaque redémarrage du QA ou reboot de la box.
-
Dans mon exemple, mavariable est affectée à l'objet self, c'est à dire l'objet QuickApp, cette variable n'est donc accessible que depuis l'une des fonctions membres de QuickApp (avant de me faire reprendre par les experts : en pratique on peut y accéder d'ailleurs, mais chut, on va pas compliquer inutilement pour l'instant) Dans ton dernier exemple, mavariable est une variable globale dans le code LUA de ton QA. C'est qui n'est pas idéal, car une bonne pratique c'est toujours de limiter la portée d'une variable au strict nécessaire. C'est un sujet qui a été abordé plusieurs fois sur le forum, mais l'information étant diluée ça et là au fil des discussions, c'est pas évident à retrouver. On pourrait transformer ta variable globale en variable locale en l'écrivant ainsi : local mavariable function QuickApp:onInit() mavariable = "Hello" end function QuickApp:ModifyVariable(value) mavariable = value end En revanche attention ce code est faux, car la variable serait alors locale uniquement à la fonction onInit() et ne serait donc pas accessible depuis la fonction ModifyVariable (qui créerait alors une autre variable, globale cette fois-ci, portant le même nom) function QuickApp:onInit() local mavariable = "Hello" end function QuickApp:ModifyVariable(value) mavariable = value end Quelques bonnes lectures :
-
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
Lazer a répondu à un(e) sujet de Lazer dans Quick App Developpeur
Si GEA redémarre tout seul, il faudra me donner les logs au moment du redémarrage, sans ça impossible de deviner le problème. Par ailleurs, mettez bien une règle qui vous envoie une notification au redémarrage de GEA (comme dans l'exemple fourni), ça évitera les "impressions" et vous aurez des certitudes sur le redémarrage (ou non) de GEA. Personnellement ça ne m'est jamais arrivé depuis 3 mois que mon GEA tourne en production, avec 150 règles environ (par contre j'ai eu quelques redémarrages de la box) Par ailleurs, est-ce que ça ne serait pas un problème plus général sur la box ? Avec des freeze ou une saturation de la RAM ? Sujet plusieurs fois abordé sur le forum. Si vous avez Domocharts, regardez les graph CPU et RAM. Perso j'en ai assez rarement des freeze, mais ça semble arriver plus souvent à @jjacques68 notamment. Parce qu'un freeze de 1, 2, 3 minutes, voire plus, ça peut expliquer les actions manquées telles que l'allumage du sèche serviette de ton exemple. Mais ça n'expliquerait pas la règle d'extinction du sèche serviette, qui n'a pas de référence horaire. Quand ça arrive, dans la HC3, le module 454, il est bien ON ? Il faut analyser les causes des comportements erratiques, sinon tu ne trouveras jamais. -
Attention si tu souhaites mettre la HC3L en passerelle derrière la HC3, il y a encore de nombreux bugs avec cette stable pour les modules esclaves (exemple : impossible de modifier leur propriétés). Fibaro travaille sur le correctif.
-
Bienvenue sur le forum
-
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
Lazer a répondu à un(e) sujet de Lazer dans Quick App Developpeur
Je mettrais un "Repeat" oui.... car le problème avec les détecteurs de mouvement, c'est que s'il se déclenche et s'arrête entre 2 boucles de GEA (toutes les 60s), alors GEA rate des mouvements. Je sais que ça m'arrive sur certains de mes scénarios, depuis la HC2. Donc le Repeat devrait permettre de contourner ce problème. -
Je ne sais pas.... je suppose que ça va tout supprimer. Sinon tu attends, ça va se purger automatiquement.
-
Non, avec updateProperty tu ne peux modifier que les propriétés, c'est à dire les valeurs qui sont dans la sous-table properties du JSON du module (visible via /api/devices/ID) Si la variable est "locale", c'est qu'elle est dans la mémoire (pile) du code LUA en cours d'exécution, donc elle n'est absolument pas accessible depuis un autre QA. C'est l'isolation élémentaire des espaces mémoires des programmes informatiques. Encore heureux... encore que des bugs/failles existent, ce qui mène aux plantages ou piratages qu'on voit parfois passer... En revanche, tu peux modifier les variables de QA (celles qui sont dans l'onglet Variables de l'interface Wzb), puisqu'elles sont stockées dans les properties du QA. Mais attention, le format est un peu spécifique, c'est une sous-table qui liste toutes les variables et leurs valeurs, cela n'est donc pas modifiable avec updateProperty, il faut passer par l'API directement.... ou plus simplement appeler la méthode setVariable du QA cible : fibaro.call(ID, "setVariable", "ma_variable", "ma_valeur") je l'ai déjà dit plusieurs fois sur le forum, mais toutes les méthodes (= fonctions) d'un QuickApp sont automatiquement exposées, elles peuvent donc être exécutées depuis un autre QA, ou bien depuis n'importe où dans le monde en passant par l'API HTTP de la box. Cela inclue donc des fonctions aussi élémentaires que self:debug() ===> fibaro.call(ID, "debug", "Injection d'un message dans le log du QA cible") Cela étant dit, tu peux créer une fonction dans un QA, qui permet de modifier une variable locale. Exemple tout simple : function QuickApp:onInit() self.mavariable = "Hello" end function QuickApp:ModifyVariable(value) self.mavariable = value end Il suffit d'appeler depuis un autre QA : fibaro.call(ID, "ModifyVariable", "Goodbye")
-
En effet, normal, il fallait écrire avec self : fibaro.setTimeout(0, function() self:loop() end) fibaro.setTimeout(3000, function() self:loop() end) Je t'ai dis, c'est pas testé, et écris à l'arrache
-
C'est un bon début Alors c'est normal, car tu as déclaré tes variables en local, donc elles ne sont connues que dans la fonction onInit(), mais pas dans loop() Voir : Ensuite, il ne faut surtout pas utiliser sleep(), ça va bloquer ton QA, donc mener à un plantage de celui-ci, voire à un reboot de la box. Il faut utiliser setTimeout() C'est de l'asynchronisme, un mécanisme pas évident à comprendre.... Voir ici : Ce que tu peux faire, c'est affecter tes variables à self (l'objet qui désigne le QuickApp en mémoire), ainsi tu peux utiliser les variables dans toutes les fonctions du QA. Pour accéder à un élément particulier d'une table, il faut utiliser les crochets, et le dièse pour compter le nombre d'éléments de la table : for i=1, #Table do print(Table[i]) end ce qui devrait donner un truc dans le genre (non testé, à affiner, mais ça te donne une base de travail) : function QuickApp:onInit() self:debug("onInit") local tempOld = self.properties.value self.Table = {} for i = 1, 10 do table.insert(self.Table, tempOld) end self:debug(json.encode(self.Table)) fibaro.setTimeout(0, function() loop() end) -- on lance la boucle end function QuickApp:loop() self:debug("loop !") table.remove(self.Table, 1) local newValue = fibaro.getValue(123, "value") -- il s'agit de l'ID de ton module température Z-Wave ou Netatmo table.insert(self.Table, newValue) self:debug(json.encode(self.Table)) local tempSum = 0 for i = 1, #self.Table do tempSum = tempSum + self.Table[i] end local tempMoy = tempSum / #self.Table self:debug("Nouvelle moyenne :", tempMoy) self.updateProperty("value", tempMoy) fibaro.setTimeout(3000, function() loop() end) -- prochaine boucle dans 3 secondes end
-
Au cas où, tu es en Wi-Fi ? Essaye de le désactiver pour passer en 4G. Sur le forum officiel, plusieurs personnes ont des problèmes avec l'appli en Wi-Fi (dans la sous-catégorie iOS, j'ai l'impression que ça ne concerne pas Android)
-
Chez moi ça marche, rien à signaler. Sur Android pour info.
-
La table c'est une variable en RAM, donc non elle n'est pas sauvegardée lors du redémarrage du QA, comme tout programme informatique en fait. On pourrait imaginer sauvegarder cette table dans une variable du QA (donc stocké dans la base de données de la HC3), mais je ne te le conseille pas du tout (impact sur les performances, usure de la mémoire flash) La solution de @jang est élégante, mais ce n'est pas une vraie moyenne glissante comme tu le voulais, et elle ne résout pas non plus le problème du redémarrage du QA. Après là tu as plusieurs notions à prendre en compte : - du LUA pur, mais c'est un faux problème car la manipulation des tables est hyper simple (je t'ai donné les 2 fonctions à utiliser) , donc on en revient à un principe de programmation en général (du coup est-ce que tu es à l'aise sur un autre langage, car tout ceci n'est que de l'algorithme) - des mathématiques.... c'est à dire comment calculer une moyenne glissante - le QA en particulier, et la façon que Fibaro propose pour mémoriser des données de façon persistante Pour ce dernier point, comme dit plus haut, je ne te conseille pas du tout de mémoriser la table complète à chaque passage dans la boucle. De toute façon le QA va calculer sa moyenne glissante via sa table en mémoire vive, et mettre à jour sa propriété "value", puisque ton QA aura comme type "com.fibaro.temperaturesensor" je suppose. Du coup, en cas de redémarrage du QA, dans le onInit() je relirais la valeur courante de la value (puisque celle-ci est bien persistante), et je m'en servirait pour initialiser ma table de 7200 valeurs. Je trouve que c'est un moyen simple et efficace de résoudre la problème du redémarrage du QA.
-
Sur HC2 j'utilise toujours l'ancienne application, qui existe depuis pas mal d'année. La connexion se fait via le cloud Fibaro, il te faut un compte, avant de choisir la HC2 et de s'y connecter dessus.
-
Si ça marche touche à rien Faut pas exagérer, incendie aucun risque Mais bon tu devrais les contacter, photo à l'appui.
-
Possible.. tu le verras facilement si le numéro de série et/ou l'adresse MAC ont changé.
-
Ah cool Oui parfois ils font payer, d'autre fois non, c'est la loterie, enfin tant mieux pour toi. Du coup j'ai du mal à comprendre quel était le problème.... mais par contre je te confirme que le clé USB recovery ne sert plus à rien et doit être débranchée depuis les firmwares > 4.500 Aïe pour l'antenne, mais du coup tu ne peux plus l'installer ? Ou juste pas la visser à fond ? Parce que ça risque de ne pas bien fonctionner du tout sans antenne... à l'extrême ça peut même cramer le chipset (un appareil avec une antenne doit toujours avoir son antenne connectée... idem pour les routeurs Wi-Fi) Je te conseille sauvegarde locale et cloud. Il y a un script sur le forum pour faire des sauvegardes automatique en local, sur un NAS. Perso il tourne chaque week-end dans la nuit de samedi à dimanche.
-
Une boucle infinie, avec une table suffisamment grande pour stocker l'historique des mesures sur 5 jours. Par exemple chaque minute sur 5 jours ça fait : 60*24*5 = 7200 éléments dans le tableau, rien de méchant. Puis avec une petite boucle for tu additionnes toutes les valeurs, tu divises par le nombre d'éléments. A chaque passage dans la boucle infinie, il faut faire un table.insert() pour ajouter la nouvelle valeur, et faire un table.delete() si l'historique dépasse 7200 valeurs.