-
Compteur de contenus
25 987 -
Inscription
-
Dernière visite
-
Jours gagnés
1 279
Tout ce qui a été posté par Lazer
-
Oh les beaux Discus En effet pour la sonde du Secure, j'avais oublié ce détail d'importance ! Dans ce cas, je chercherais du coté de Qubino, ils ont un micro-module ZMNKID1 Flush On/Off Thermostat 2 avec sonde déportée. Je pense qu'il ne fera pas de PID, mais si tu peux régler un hystérésis de 0.2°C, tu auras le résultat que tu voulais. A chercher dans la doc. https://www.domadoo.fr/fr/peripheriques/4971-qubino-micromodule-thermostat-encastrable-z-wave-zmnkid1-flush-onoff-thermostat-2-3830062071710.html https://qubino.com/products/flush-on-off-thermostat-2-2/
-
Détecter les erreurs et protéger l'exécution d'un script LUA avec pcall() Il existe déjà un vieux sujet de @Shad, mais je vais essayer d'être un peu plus exhaustif, en prenant en compte les nouveautés apportées par les scènes sur HC2 puis les QuickApp sur HC3 : l"utilisation de la librairie net.HTTPClient() et l'exécution asynchrone du code LUA. Autre sujet détaillant l'utilisation de net.HTTPClient() à lire au préalable : Durant l'exécution d'un script LUA, une erreur peut survenir, susceptible de planter le script, celui-ci s'arrête alors brutalement et la suite du code n'est jamais exécutée. Je paraphrase l'explication de @Krikroff : Pour faire simple: La fonction pcall() permet l’exécution du code en mode "protégé" ou "encapsulé", c'est à dire qu'il ne lèvera pas d' erreur dans le processus de votre box si jamais le code provoquait une erreur. Ainsi, le fil d'exécution des Scènes et des QuickApps est protégé. Aussi à savoir: pcall() retourne true ou false en fonction de la réussite du code mais peut aussi retourner un résultat issu de la fonction en utilisant la méthode interne error(). La fonction pcall() peut-être utilisée pour faire en LUA l'équivalent du try...catch pour ceux qui connaissent. Des exemples ici pour comprendre : Programming in LUA : 8.4 - Error Handling and Exceptions Programming in LUA : 8.5 – Error Messages and Tracebacks Exemple n°1 : protection de http:request() Le premier usage de pcall() est pour protéger l'exécution de la fonction http:request() car celle-ci peut planter, par exemple si l'URL est mal formée : local http = net.HTTPClient() local url = "http://192.168.1.1/chemin/page?argument=valeur" local status, err = pcall(function() http:request(url, { success = function(response) -- Suite des traitements... end, error = function(err) -- Gestion de l'erreur (connexion impossible) end, options = { -- options éventuelles... } }) -- http:request() end) -- pcall() if not status then -- Gestion de l'erreur attrapée par pcall() print(err) end Exemple n°2 : protection de json.decode() De plus, pcall() est également très utile (voire indispensable) pour une autre fonction qui a la fâcheuse habitude de planter : json.decode() si le JSON donné en argument est mal formaté. Exemple : local status, jsonTable = pcall(function() return json.decode(response.data) end) if status then -- Suite des traitements... else print(jsonTable or "json.decode() failed") end Dans cet exemple, la variable jsonTable contiendra soit le tableau décodé (résultat de json.decode()), soit le message d'erreur (résultat de pcall()) Exemple n°3 : protection complète de http:request() et json.decode() Par ailleurs, il faut noter que dans le premier exemple avec http:request(), les fonctions success() et error() sont des fonctions de callback appelées après l'exécution de la requête, donc elles sont asychrones. De ce fait, leur contenu n'est plus protégé par la fonction pcall(). Par conséquent, si on combine les 2 exemples précédents, à savoir la requête HTTP, puis le décodage du résultat JSON, cela donne une structure de code comme suit : local http = net.HTTPClient() local status, err = pcall(function() http:request(url, { success = function(response) local status, jsonTable = pcall(function() return json.decode(response.data) end) if status then -- Suite des traitements... else print(jsonTable or "json.decode() failed") end end, error = function(err) -- Gestion de l'erreur (connexion impossible) end, options = { -- options éventuelles... } }) -- http:request() end) -- pcall() if not status then -- Gestion de l'erreur attrapée par pcall() print(err) end De cette façon, le code LUA est parfaitement protégé. Exemple n°4 : interruption conditionnelle de l'exécution avec assert() La fonction assert() permet de tester une condition. Si la résultat est false, dans ce cas elle déclenche l'erreur qui sera attrapée par pcall() : local http = net.HTTPClient() local status, err = pcall(function() -- Ici mon code s'exécute et effectue plein d'actions... local device = api.get("/devices/127") assert(type(device) == "table", "Le module 127 est introuvable") -- Suite du code si tout se passe bien... end) -- pcall() if not status then -- Gestion de l'erreur attrapée par pcall() print(err) end Dans cet exemple j'ai testé si le résultat d'un appel à api.get() s'est bien passé, mais on pourrait tester n'importe quel autre cas de figure. Exemple n°5 : interruption inconditionnelle de l'exécution avec error() La fonction error() permet de forcer le déclenchement d'une erreur qui sera attrapée par pcall() : local http = net.HTTPClient() local status, err = pcall(function() -- Ici mon code s'exécute et effectue plein d'actions... if ma_condition then error("Un message d'erreur") end -- Suite du code si tout se passe bien... end) -- pcall() if not status then -- Gestion de l'erreur attrapée par pcall() print(err) end J'espère que ce petit tutoriel sera utile, vous pouvez maintenant utiliser pcall() dans vos code, combiner les différents exemples ci-dessus, etc.
-
Et bien le Secure SRT 321 (je crois que la nouvelle version Z-Wave+ c'est SRT 322) Il a une régulation PID qui sera beaucoup plus précise que ton hystérésis de 0.2°C que tu décris dans ton expression de besoin. Car si tu as un tel hystérésis, avec l'inertie, tu risques d'avoir des variations de températures beaucoup plus importantes... surtout avec un aquarium, ça a une grosse inertie (quelle capacité d'ailleurs par curiosité ? J'avais un 450 litres avant de me mettre à la domotique) Le Secure, tu fais une association directe avec un module type relai (ils vendent le leur, mais on peut utiliser un micro-module Fibaro FGS 213 ou 214), et il va réguler la température tout seul, avec l'algorithme PID qui prend en compte l'inertie. Remarque : je n'ai jamais refait mon aquarium, mais si un jour je m'y remet, j'avais plutôt envisagé de le domotiser avec un IPX800 installé dans le meuble en dessous, dédié à cet usage. A la place des bons vieux programmateurs mécaniques sur prise 230V. Avec ses capteurs et actionneurs, il pourrait piloter en tout autonomie l'aquarium, de façon totalement autonome et super fiable : - capteur de température => régulation de température - gestion des éclairages en fonction des horaires - mesure PH - etc
-
Netatmo, le script n'est pas de moi, j'ai juste ajouté quelques bricoles supplémentaires (les niveaux de batteries), mais bon, ça n'a jamais posé problème, et il fait un appel http toutes les 10 minutes, donc rien de méchant, ça ne posera jamais de problème. Pour Network Monitor, il faudra en effet que je fasse une nouvelle version... plus tard
- 58 réponses
-
Je pense qu'il n'aime pas les doubles quotes dans l'URL, il faudrait que tu fasses un urlencode() de ta chaine avant de la donner à http:request() Mais je suis surpris quand même, est-tu certain de la nécessité de mettre des guillemets ? J'utilise l'API Synology pour d'autres usages, et je n'ai jamais eu besoin... et c'est même carrément pas standard comme pratique, en général on utilise uniquement des caractères classiques dans les URL, autant que possible.
-
Ah ouais, très étrange comme comportement. En premier lieu assure toi d'avoir un backup (local et en cloud). Ensuite, tu pourrais tenter un recovery afin de réinstaller proprement le système, puis restaurer ta dernière sauvegarde. Peut être que ça remettra les choses d'aplomb
-
@jjacques68 j'ai l'impression que tu n'as pas compris ce que j'ai écris. Moi je parlais des différences que tu trouves à partir du test n°2. Le test n°1, tout va bien, donc il n'y a rien de plus à en dire
-
Numéro de série / Date d'Achat des box HC3, HC2 et HCL
Lazer a répondu à un(e) sujet de Lazer dans HC 2 & Lite
- 265 réponses
-
- numéro de série
- hc2
-
(et 1 en plus)
Étiqueté avec :
-
Sans certitude, mais je me demande si cette différence entre les route réellement empruntée et la route stockée dans l'API, ne serait pas dû à la différence entre la route dans le sens Contrôleur => Module, et la route dans le sens Module => Contrôleur. Il faudrait tester les 2 cas de figure : - envoi d'un ordre depuis la box - envoi d'un retour d'état depuis le module Ainsi tu verrais si la route empruntée est la même dans les 2 cas. Et sinon, tu sauras à quelle direction de route correspond l'information stockée dans l'API.
-
Quand tu dis "Plus aucun moyen d'accéder à l'interface PC ou Smartphone", concrètement il se passe quoi ? Tu voir la mire de login, aucune connexion possible, un code d'erreur genre 503, les boules bleues ? Est-ce que la box répond au ping quand elle est plantée ?
-
Maintenant que tu le dis... Je viens de tilter En janvier j'ai eu une panne d'Internet (fibre coupée pendant quelques jours) Donc Network Monitor ne pouvais plus joindre Google, et faisait plusieurs tentatives, avant de me notifier. Ce que je ne comprenais pas, c'était pourquoi de temps en temps, aléatoirement pendant toute cette période, Network Monitor me signalait également des machines sur mon LAN en erreur (alors que tout fonctionnait parfaitement en local). Donc maintenant c'est clair, il faut avoir un seul self.http = net.HTTPClient() dans tout le QuickApp, il gère parfaitement la situation lorsque de nombreuses requêtes sont exécutées pseudo-simultanément. Ce qui n'est pas le cas lorsqu'on a plusieurs instances de HTTPClient dans des variables différentes. Voilà, là on a appris un super truc
- 58 réponses
-
- 1
-
-
Faut bien comprendre que le fonctionnement sans neutre est un hack inventé à l'époque des lampes à incandescences.... et ça n'a jamais bien fonctionné avec les LED. Au mieux, ça "marchote", au pire ça ne fonctionne pas du tout J'insiste, d'autant plus si tu veux domotiser toute ta maison, il faut que tu passes le maximum de neutre dans les gaines existentes. Il en restera bien quelques unes pour lesquelles il y a un coude trop prononcé empêchant de passer le fameux fil de neutre, tant pis pour celles-ci, mais au moins du auras la majorité de tes ampoules qui fonctionneront bien en LED. Ou alors tu fais comme moi, un gros stock d'ampoules à incandescence / halogènes, et tu en profites (en fait je mixe avec des LED, mais le moins possible, et uniquement là où j'ai le neutre) Ta lampe témoin ça ne n'en sais rien, elle est intégrée à ton interrupteur, tu l'as soue les yeux, pas moi.... ça diffère d'un modèles à l'autre. Chez Legrand elle se clipse et se retire, chez d'autres je ne sais pas.
-
Essaie d'enlever la lumière témoin de l'interrupteur, elle n'aime pas le courant de fuite imposé pour retourner vers le neutre. Sinon, la meilleure solution c'est de passer un fil de neutre pour t'affranchir de tous ces problèmes... mais pas simple à mettre en œuvre (aiguille en nylon, lubrifiant, et pas mal d'huile de coude)
-
Oui et non... ça dépend... Si seulement 2 fonctions ont besoin de se partager la table, autant la passer en paramètres Si par contre toutes les fonctions d'un même QuickApp sont susceptibles d'utiliser cette même table, alors autant l'attribuer au QuickApp (self.xxx) Je ne saurais dire quelle méthode est meilleure que l'autre, mais c'est plus du bon sens et de l'organisation logique du code.
- 58 réponses
-
- 1
-
-
Oui je comprends.... c'est sûr que les box Fibaro sont simples à prendre en main mais beaucoup trop limitées par leur mode bloc (que je n'utilise pas du tout personnellement) Et à l'inverse elles permettent de faire plein de choses, mais il faut savoir coder en LUA... pas évident du tout. Entre les deux, il y a comme un gouffre. Je viens de regarder, j'ai bien l'impression que les modules liés n'existent plus sur HC3, donc ça ne va pas t'aider... EDIT : Personnellement, je n'ai jamais aimé le principe de réguler la température depuis la box, ça veut dire que si elle plante, même temporairement, tu n'as plus aucune régulation, et un chauffage qui ne cesse de chauffer, .... ou bien de refroidir. Je trouve que l'idéal reste le thermostat physique (exemple Secure SRT, Heatit, etc) qui gère la régulation tout seul comme un grand, la box domotique se contente d'envoyer des températures de consignes Ainsi en cas de panne de la box, on perd la programmation des horaires, mais pas la régulation de température.
-
Merci pour ton test qui confirme que l'option n°1, c'est à dire la variable self.http unique dans tout le QuickApp est la meilleure. On ne maitrise pas ce qui se passe à l'intérieur de la librairie net.HTTPClient, codée en C, et visiblement elle gère parfaitement les requêtes simultanées C'était un peu le doute que j'avais eu en portant Network Monitor sur HC3, et par précaution j'ai choisi de créer une variable http pour chaque serveur à monitorer. Visiblement c'est inutile, et je pourrais utiliser une variable self.http unique. Bon après c'est pas pour le peu de mémoire que consomme ce QuickApp que ça va changer grand chose... Disons que c'est toujours utile car ça permet de libérer la mémoire... mais les QuickApps étant stables par nature, ce xx = nil n'est pas indispensable comme il l'était pour les VD sur HC2 (cela dit on n'a jamais trop su pourquoi ils plantaient, jusqu'à ce que Fibaro corrige le bug) Plus en détail : Pour une variable locale, il est inutile de forcer sa libération avec xxx = nil à la fin du bloc de code dans laquelle elle a été déclarée, car le Garbage collector se chargera de faire la ménage tout seul Pour une variable du QuickApp self.xxx, la question ne se pose pas, car si on crée une variable dans le QA, c'est qu'on veut la garder pendant toute la durée de vie du QA, donc aucune raison de la supprimer (sinon on aurait choisit une variable locale) Pour une variable globale, dans ce cas, je vois 2 cas de figure : soit on a sciemment choisi qu'elle soit globale pour être accessible par tout le monde (le QuickApp et les autres objets dans d'éventuels autres fichiers LUA.... mais c'est une mauvaise pratique soit on a involontairement défini la variable en local pour un usage ponctuel, et dans ce cas il faut manuellement penser à la supprimer avec xxx = nil, sinon elle restera allouée en mémoire jusqu'à la fin de l'exécution du programme (dans le cas d'un QuickApp => jamais (ou bien redémarrage du QA, reboot de la box)) et le garbage collector ne pourra jamais la supprimer Enfin, pensez que quand on veut passer une variable entre 2 fonctions, la meilleure solution est souvent le passage par paramètre. A ce sujet, quand on passe une string ou un number en paramètre, c'est une copie. Alors que quand on passe une table, c'est une référence... si bien que la fonction peut modifier la table originale en ne pensant modifier que sa propre table... méfiance, parfois le comportement est voulu, parfois pas ! Impossible, comme dit hier sur un autre topic, les QA sont mono-threadés, le code ne peut jamais s'exécuter simultanément. Il y a une file d'attente, et à chaque fois qu'on appelle un QA (un bouton, une fonction, une action, un événement, un settimout dans le cas d'une boucle, etc), tout cela est mis en file d'attente, et exécuté en série.... cf la discussion sur l'asynchronisme Et franchement, je trouve ça mieux ainsi. Pour avoir déjà programmé en multi-thread, c'est vraiment chaud, le contenu d'une variable peut être modifié entre 2 lignes consécutives de code, si un autre thread se déroule au même moment. Il faut gérer des mutex, etc, une gymnastique pas évidente. En fait c'est différent, sur HC2 chaque instance de scène s'exécutait dans un processus (au sens Linux du terme) différent, c'est à dire un programme totalement séparé, avec son propre espace mémoire, avec sa propre copie du code, des variables, de la pile, etc. Du coup on avait une étanchéité totale entre les instances de scènes, il était impossible pour elles de partager les mêmes variables (sauf à passer par des variables globales) Sur HC3, chaque QuickApp est un processus (mono-threadé donc), et chaque scène est un processus aussi (toujours mono-threadé) Et Fibaro, au moins jusqu'au firrmware actuel, interdit le démarrage de plusieurs "instances", c'est à dire plusieurs processus Linux.
- 58 réponses
-
- 1
-
-
Ismartgate - Nice - Fibaro - Maison
Lazer a répondu à un(e) sujet de JLT dans Actionneurs & Ouvrants (Portail, volets, piscines, ...)
Là j'en sais rien.... PS : ne cite pas le message précédent au tient, c'est inutile, et pire, ça alourdi la lecture. -
Pas sûr de moi, mais à priori utiliser une seule variable HTTPClient pour l'ensemble du QuickApp est valable, donc l'option n°1. Cela dit l'option 2 est valable aussi, mais tu vas redéfinir un nouvel objet à chaque fois, donc ça prend du temps à initialiser, ça consomme plus de RAM, etc. De mémoire il me semble que c'est cette dernières option que j'utilise dans Network Monitor (mais c'est le seul, tous mes autres QuickApps ont un seul objet HTTPClient global) Cependant, attention il y a une (grosse) erreur dans ton code dans l'option 2 Tu définis ta variable ainsi au sein de chaque fonction : http = net.HTTPClient() Donc... http est global ! Si bien qu'à chaque appel de l'une des autres fonctions, tu redéfinies... la même variable ! Bref, du travail inutile. Autre chose, de façon générale, il faut éviter les variables globales : - on ne maitrise pas leur portée, elle peuvent entrer en conflit avec d'autres variables du même nom mais dont la portée serait locale... soit dans une fonction, une boucle imbriquée, ou bien carrément dans un autre fichier (puisque les QA peuvent maintenant accueillir plusieurs fichiers LUA) - cela consomme plus de RAM, car une variable globale n'est jamais libérée par le Garbage Collector (par définition, elle doit rester tout le temps accessible par tout le monde au sein du programme.... sauf si on la détruit explicitement avec http = nil, ce que personne ne pense à faire) - et enfin, l'accès aux variables globales est plus lent (les variables globales sont stockées dans un super tableau _G que LUA doit parcourir pour trouver la bonne entrée) Donc la bonne syntaxe dans chaque fonction pour l'option 2 serait : local http = net.HTTPClient() De façon similaire, dans la première option, tu as aussi défini une variable globale. Il vaudrait mieux la stocker dans le QuickApp, lors de son initialisation : QuickApp:onInit() self.http = net.HTTPClient() end Et on appelle ensuite self.http à chaque fois que l'on veut s'en servir.
- 58 réponses
-
Modeste installation de débutant
Lazer a répondu à un(e) sujet de ToTo Buzet dans Mon installation domotique
Mais les parmaètres d'IP statiques, c'est dans la HC3 qu'il faut les configurer ! Et surtout tu choisis une adresse IP qui soit en dehors de la plage DHCP, sinon tu vas avoir des conflits. Il faudra aussi bien renseigner la passerelle et le DNS, normalement c'est l'adresse de ton routeur Internet. Ensuite tu vérifies que tu y accèdes bien depuis tes 2 PC (celui sous Windows et celui sous MacOS) Puis après on verra pour l'accès distant -
Ismartgate - Nice - Fibaro - Maison
Lazer a répondu à un(e) sujet de JLT dans Actionneurs & Ouvrants (Portail, volets, piscines, ...)
Il faut créer un scénario qui va modifier la valeur de ta variable globale à chaque changement d'état de ton module => Une scène avec comme condition de déclenchement l'état du portail. Mais c'est pas terrible, compliqué.... Hoobs ne peut pas aller lire directement l'état des modules ? Passer par les variables globales, c'est un peu lourd.... on le faisait à l'époque de la HC2 car on n'avait souvent pas le choix, mais sur HC3 c'est un peu dommage -
Bienvenue sur le forum
-
En fait, Fibaro ne propose pas de thermostat en natif dans la box (contrairement à ce qui existe chez Zibase, eedomus, Jeedom, ou HASS) Le panneau de climat permet de configurer un planning horaire de températures, dont la consigne sera envoyé aux thermostats les modules de type thermostats (donc qui acceptent une consigne de température) sont de 2 types : Modules physiques Z-Wave, tels que le Secure SRT-321, ou bien encore le Remotec ZTX-120 (encore que celui-ci ne soit pas un vrai thermostat, puisque la consigne de température qu'il reçoit via Z-Wave est retransmis par infra-rouge vers la pompe à chaleur). QuickApps : il s'agit des modules virtuels, que l'utilisateur est libre de créer à volonté.... sauf que... il faut coder en LUA, car le QuickApp de base ne fait rien du tout. Sur HC3 à ma connaissance personne n'a encore développé et partagé de QuickApp de type thermostat avec vraie régulation de température (algorithme PID, etc) Enfin, sur HC2 il existait un mécanisme assez simple, ultra basique, mais efficace : les modules liés. Je n'ai même pas regardé si ça existe sur HC3, peut être. Mais dans l'immédiat ça correspondrait à ton besoin, il permet d'associer une sonde de température avec un actionneur relai, afin de faire du ON/OFF sur le chauffage. Basique ça il ne saura pas prendre en compte l'inertie du volume à chauffer, mais fonctionnel sans effort.
-
Déjà il te dit clairement où est l'erreur : dans la string qui contient ton URL. Je ne sais pas quel éditeur de code tu utilises, mais Notepad++ par exemple, permet la coloration du texte selon le langage utilisé (qu'il détecte automatiquement si le fichier porte l'extension .lua), ça aide énormément à détecter les erreurs de syntaxe. pcall() s'utilise de cette façon là : local status, err = pcall(function() http:request(url, { success = function(response) -- Suite des traitements... end, error = function(err) -- Gestion de l'erreur end, options = { -- options... } }) -- http:request() end) -- pcall() if not status then -- Gestion de l'erreur print(err) end Cela évite de faire planter le script, permet de traiter l'erreur, et de continuer l'exécution. Pour information pcall() est également très utile (voire indispensable) pour une autre fonction qui a la fâcheuse habitude de planter : json.decode() si le JSON donné en argument est mal formaté. Exemple : local status, jsonTable = pcall(function() return json.decode(response.data) end) if status then -- Suite des traitements... else print(jsonTable or "json.decode() failed") end
-
Euh... mais fibaro:debug() ça n'existe plus non ? C'était sur HC2 ça. Après tu es dans une scène, je ne sais pas trop, je ne code que dans les QuickApps moi Utilise un simple print() à la place pour débugguer
-
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
Lazer a répondu à un(e) sujet de Lazer dans Quick App Developpeur
En parlant de GEA, de Variable, et de QuickApp, le hasard veut que ce soit j'ai justement implémenté une nouvelle option "VariableQuickApp" pour GEA, qui permettra d'aller lire et modifier les variables des QA depuis les règles GEA