Sowliny Posté(e) le 21 décembre 2021 Signaler Posté(e) le 21 décembre 2021 Merci à tous pour les réponses ! Qui m'ont fait bien plaisir... il y a une heure, Fredmas a dit : ce topic est plus à considérer comme un café philo du débutant passionné C'est bien comme cela que je le voyais - je suis aussi du genre à créer par moi-même, pas de clé-en-main ! Il y a 1 heure, Fredmas a dit : J'aurais pu tout faire dans le même facilement, mais pour l'instant je préfère séparer pour ne pas tout craquer en cas de crash du QA. D'accord aussi sur cela. De petites structures sont bien plus faciles à maintenir qu'une grosse (usine à gaz !). A propos je n'ai pas compté (il faudra que je le fasse à l'occasion), mais je dois avois installé une cinquantaine de modules divers... Et c'est certain que ca va fumer !!! Mais quoi de plus plaisant ? Très joyeux Noël à tous !
Fredmas Posté(e) le 21 décembre 2021 Auteur Signaler Posté(e) le 21 décembre 2021 il y a 10 minutes, Sowliny a dit : Et c'est certain que ca va fumer !!! Mais quoi de plus plaisant ? Très joyeux Noël à tous ! Parfaitement d'accord Joyeux Noël à toi également ! 1
couillerot Posté(e) le 22 décembre 2021 Signaler Posté(e) le 22 décembre 2021 (modifié) Bienvenue Sowliny dans le club des débutants chevronnés ! tout comme Fredmas, je n'ai plus une seule variable globale dans le panneau ad'hoc et c'est ma plus grande "victoire" et joyeux Noel à tous ! Stef Modifié le 22 décembre 2021 par couillerot 3
Sowliny Posté(e) le 22 décembre 2021 Signaler Posté(e) le 22 décembre 2021 Merci Couillerot, Hé ouiii... J'en suis à environ 150 VG ! (ce n'est pas bien sûr un critère de gloire ) Avec une quarantaine de scène... Mais tout cela est un héritage direct et adapté de ma HC2. Ce qui veut dire que je n'exploite pas du tout encore les possibilités intrinsèques de la HC3. (ouf... j'ai trouvé une excuse !). Comme tout tourne bien maintenant (comme je l'ai déjà dit, ma HC3 est passée directement en prod - et je suis conscient que ce n'est pas la meilleure chose que j'aie faite ) je vais pouvoir expérimenter les "nouvelles technologies" . Et je repenserai à cette discussion quand j'aurai moi aussi apuré toutes (?) mes VG.
jojo Posté(e) le 3 septembre 2022 Signaler Posté(e) le 3 septembre 2022 salut @Fredmas, merci pour ce sujet très détaillé. Comme il m'est impossible de parcourir tous les posts de ce sujet et que ma question TRES basique a surement déjà été posée, pourrais-tu me répéter la réponse SVP ? Question : Depuis la fonction B du QA A, je souhaite appeler la fonction D du QA C, en lui passant un paramètre. J'ai essayé ceci, et évidemment ça ne fonctionne pas : dans le QA A function QuickApp:B() ... C:D("test") ... end dans le QA C function QuickApp:D(param) ... end merci pour la future réponse que je suspecte être facile
Lazer Posté(e) le 3 septembre 2022 Signaler Posté(e) le 3 septembre 2022 fibaro.call() Doc : https://manuals.fibaro.com/home-center-3-quick-apps/ Chapitre : Mapping actions to methods 1 1
jojo Posté(e) le 4 septembre 2022 Signaler Posté(e) le 4 septembre 2022 tout est dans hub.call() (comme d'hab) (merci pour le lien et l'indication du chapitre )
mikael2235 Posté(e) le 27 octobre 2022 Signaler Posté(e) le 27 octobre 2022 Hello everybody, Je poste ce petit message, car je vais enfin entammer ma migration HC2->HC3 (depuis presque un an que j'ai mon HC3), car cela représente un travail monstre (bcp de LUA sur mon HC2) ! Ne m'en voulez pas, je débute avec les QA :-) Mon premier cas, je souhaite faire un QA pour faire clignoter un voyant lumineux. J'ai donc fait ce QA avec deux boutons ON / OFF que je pourrais activer via d'autres scenes ou QA. ça marche presque ! j'arrive bien à passer du OFF au ON, mais pas l'inverse. Quand je suis dans ma boucle while, je press OFF, et rien ne se passe. Ma variable ne passe pas à OFF, et donc la boucle ne s'arrête pas ! Pouvez vous me guider ? Merci bien -- TEST QA function QuickApp:onInit() self:debug("onInit") end function QuickApp:Cligno_ON() self:setVariable("ClignoRouge", "ON") self.cligno = self:getVariable("ClignoRouge") self:trace("var cligno = "..cligno) self:loop() self:trace("Mise en marche du cligno via le bouton") end function QuickApp:Cligno_OFF() self:setVariable("ClignoRouge", "OFF") self.cligno = self:getVariable("ClignoRouge") self:trace("var cligno = "..cligno) self:loop() self:trace("Mise en arret du cligno via le bouton") end ---------------------------------------------------------- --- Boucle loop ---------------------------------------------------------- function QuickApp:loop() self.cligno = self:getVariable("ClignoRouge") self:trace("var cligno = "..cligno) while self.cligno == "ON" do hub.sleep(1000) hub.call(79, 'turnOn') self:updateView("label1", "text", "ON") hub.sleep(1000) hub.call(79, 'turnOff') self:updateView("label1", "text", "OFF") self.cligno = self:getVariable("ClignoRouge") self:trace("var cligno = "..cligno) end end
jang Posté(e) le 27 octobre 2022 Signaler Posté(e) le 27 octobre 2022 Your while loop will not give any time for button callbacks to call your Lua functions or update UI i.e. function QuickApp:Cligno_ON() and function QuickApp:Cligno_OFF() You need to use something like setTimeout to give time to your button handlers...
mikael2235 Posté(e) le 28 octobre 2022 Signaler Posté(e) le 28 octobre 2022 Il y a 14 heures, jang a dit : Your while loop will not give any time for button callbacks to call your Lua functions or update UI i.e. function QuickApp:Cligno_ON() and function QuickApp:Cligno_OFF() You need to use something like setTimeout to give time to your button handlers... Hello jang, I've tried with setTimeout function in below code. I get the blinking ok, but I don't understand how should I do to stop it ? It seems I have the same problem as before and can't stop it. Thanks, function QuickApp:loop(timer) self:trace("loop") hub.sleep(1000) hub.call(79, 'turnOn') hub.sleep(1000) hub.call(79, 'turnOff') fibaro.setTimeout(2000, function() self:loop() end) end
jang Posté(e) le 30 octobre 2022 Signaler Posté(e) le 30 octobre 2022 (modifié) -- TEST QA function QuickApp:onInit() self:debug("onInit") end local timer function QuickApp:Cligno_ON() self:setVariable("ClignoRouge", "ON") self.cligno = self:getVariable("ClignoRouge") self:trace("var cligno = "..cligno) if not timer then self:loop() end self:trace("Mise en marche du cligno via le bouton") end function QuickApp:Cligno_OFF() self:setVariable("ClignoRouge", "OFF") self.cligno = self:getVariable("ClignoRouge") self:trace("var cligno = "..cligno) if timer then timer=fibaro.clearTimeout(timer) end self:trace("Mise en arret du cligno via le bouton") end ---------------------------------------------------------- --- Boucle loop ---------------------------------------------------------- function QuickApp:loop() self:trace("loop") hub.sleep(1000) hub.call(79, 'turnOn') hub.sleep(1000) hub.call(79, 'turnOff') timer = fibaro.setTimeout(2000, function() self:loop() end) end Modifié le 30 octobre 2022 par jang
mikael2235 Posté(e) le 30 octobre 2022 Signaler Posté(e) le 30 octobre 2022 Hello @jang, Thanks for your help, and for the code. It works very well !
jojo Posté(e) le 30 octobre 2022 Signaler Posté(e) le 30 octobre 2022 @mikael2235, juste pour ma "culture", self.cligno c'est la même chose que local cligno ?
vravolta Posté(e) le 2 février 2023 Signaler Posté(e) le 2 février 2023 Alors à mon tour de poser une question de base su comment coder proprement en QuickApp: J'ai une fonction, qui travaille en asynchrone (socket TPC) et qui va lire un registre sur mon onduleur. J'ai par ailleurs une fonction, à la logique synchrone, qui fait une boucle for et qui permet de lire l'ensemble des registres. Ceci a pour effet de m'envoyer une rafale de commandes asynchrones dont chacune a sa fonction callback. Et ce que je voudrais, c'est qu'une fois le dernier callback asynchrone effectué, je puisse reprendre le cours de mon exécution synchrone, sachant que rien ne me dit que le dernier callback à terminer soit celui du dernier registre lu. Donc en gros, on parle d'une situation où on n'est plus à gérer avec un unique callback mais une fonction où il y en a 10 qui tournent en parallèle. Ca ressemble donc à un truc du style: for _, register in pairs(register) do registerscan(registerNumber, register.callback) end self:debug("Scan terminé") Et registerscan envoie un message via un TCP socket, recoit une réponse et la traite et je voudrais que le self:debug ne se produise que quand chaque callback a fini de s'exécuter A ce stade, le seul moyen que j'arrive à envisager pour ca est qu'à chaque appel à registerscan, j'incrémente un compteur (variable globale) et qu'à chaque fin de chaque callback, je décrémente ce compteur et que mon self.debug soit une boucle infinie, stoppé quand le compteur vaut 0. Mais je trouve ca mochissime et je veux croire qu'il existe une manière propre de faire que ce soit appelé via une utilisation intelligente de callbacks plutot que via une boucle infinie et une variable globale. Si vous avez une idée pour résoudre ce challenge, je suis preneur!
jang Posté(e) le 2 février 2023 Signaler Posté(e) le 2 février 2023 Your debug at the end is a callback when all are done. see https://forum.fibaro.com/topic/42993-wait-until-httprequest-returns/?do=findComment&comment=181106
vravolta Posté(e) le 2 février 2023 Signaler Posté(e) le 2 février 2023 Ok, I think I got it for the join callback. However, I have a few remaining understanding questions: - why do you use this "complicated" syntax : for i=1,2*n,2 do local a=args[i+1] a[#a+1]=nsucc a[#a+1]=nerr args[i](table.unpack(a)) end and not this simple one: for i=1,2*n,2 do args[i](args[i+1],nsucc, nerr) end I don't understand why you populate a table with values to then unpack the table because your function needs values and not a table. then my second point is that your join callback function calls a predefined number of requests. It can be 3, 4, 5 or whatever http requests I want, but this number is fixed by the syntax (5 calls in your example). In my case, I have a loop and the number of calls it will generate will only be known at execution time, depending on how many registers are described in my registers table. Thus, at the time of writing code, I'm not in a position to know the correct number of arguments to pass to join. Is there a syntax trick to build the correct join call at execution time ? Something like building a string in my loop with the right syntax and then passing that string to something that will execute it? Last, I'm not sure I understand correctly this part of the http request: error = err or function(err) error(url,err) end So please, correct me if I'm wrong: My understanding is that if err is provided as an argument in the call to SendRequest, then this function will be called in case of error while calling http:request. But if err is not provided in the list of arguments when calling SendRequest, a default function will be used and it will be the standard error function function of http:request but with the url parameter fixed, making it a one parameter function. So I understand that the second "err" of the line are just "blind" ((local?) variables = they could have been replaced by any name. So, this code would also have worked: error = err or function(err1) error(url,err1) end To say it differently, the first err has to be err and nothing else and refers to the last argument of SendRequest. the next 2 occurrences of err just refer to a local variable and it's just a coincidence that it bears the same name as the first occurrence of err. Am I correct? Thanks again for your help, much appreciated!
jang Posté(e) le 2 février 2023 Signaler Posté(e) le 2 février 2023 Il y a 9 heures, vravolta a dit : Ok, I think I got it for the join callback. However, I have a few remaining understanding questions: - why do you use this "complicated" syntax: and not this simple one: I don't understand why you populate a table with values to then unpack the table because your function needs values and not a table. It's just to cater for a variable number of arguments in the provided table. Now it's just a table with an single url so it is kind of an overkill (and then we tuck on the success and error handlers at the end). By allowing join to take a function with unknown number of arguments we keep it generic and let the sendRequest deal with the number of args. Il y a 9 heures, vravolta a dit : then my second point is that your join callback function calls a predefined number of requests. It can be 3, 4, 5 or whatever http requests I want, but this number is fixed by the syntax (5 calls in your example). In my case, I have a loop and the number of calls it will generate will only be known at execution time, depending on how many registers are described in my registers table. Thus, at the time of writing code, I'm not in a position to know the correct number of arguments to pass to join. Is there a syntax trick to build the correct join call at execution time? Something like building a string in my loop with the right syntax and then passing that string to something that will execute it? Yes you need the count the number of calls and use that later to count down... because register is a key/value table you can't just use #register... I'm not sure how your 'registerscan' is implemented but I assume that the callback is called at success. Then I would add another callback for errors and implement it something like this local function scallAll(register) local n,finish=0 for _, register in pairs(register) do n=n+1 local cb = register.callback registerscan(registerNumber, function(res) cb(res) isFinished() end, -- success callback function(err) print("Err:",err) isFinished() end -- error callback ) end function isFinished() n=n-1 if n==0 then self:debug("Scan completed") end end end Il y a 9 heures, vravolta a dit : Last, I'm not sure I correctly understand this part of the http request: So please, correct me if I'm wrong: My understanding is that if err is provided as an argument in the call to SendRequest, then this function will be called in case of error while calling http:request. But if err is not provided in the list of arguments when calling SendRequest, a default function will be used and it will be the standard error function function of http:request but with the url parameter fixed, making it a one parameter function. So I understand that the second "err" of the line are just "blind" ((local?) variables = they could have been replaced by any name. So, this code would also have worked: To say it differently, the first err has to be err and nothing else and refers to the last argument of SendRequest. the next 2 occurrences of err just refer to a local variable and it's just a coincidence that it bears the same name as the first occurrence of err. Am I correct? Thanks again for your help, much appreciated! Yes, it's just a reuse of the name 'err'. The second err in "function(err) ..." shadows the previous definition. What's bother me now is that the code is buggy as the call to the builtin error function can't take two string error messages. The correct code would have been error(url..err)
vravolta Posté(e) le 6 février 2023 Signaler Posté(e) le 6 février 2023 Now that I could manage my issue with the join callback trrick, here comes another challenge: with the syntax for a,b in pairs(MyTable) do blabla end, I can perform a full scan of a table. But is there a way to stop the scan once I've found what I wanted in MyTable. In other words, is there a syntax to exit a for loop before the fullscan is terminated or is there a possibility to have a while loop on a table?
TitiXsi Posté(e) le 8 février Signaler Posté(e) le 8 février (modifié) Hello, j'ai une question un peu naze... mais je ne trouve pas la solution J'ai déclaré dans une QA plusieurs ID de devices local ID_1 1234 local ID_2 4567 ... Je souaiterai appeler avec un for ces devices mais je n'arrive pas à faire évaluer une variable qui est une chaine de caractère et qui doit représenter l'ID d'un device... J'ai essayé plusieurs chose, mais sans le statement adéquate "evaluate" ou autre qui permet dévaluer ID_1, je reste bloqué for i=1,2 do print(i) local ID_device_string = 'ID_'..i local ID_device_number = evaluate(ID_device_string) print("Device : ",ID_device_string, " under analysis...",ID_device_number) value = hub.getValue(ID_device_number, "power") print("value_"..i.." :",value) end Merci pour votre aide. Modifié le 8 février par TitiXsi
Lazer Posté(e) le 8 février Signaler Posté(e) le 8 février Tu ne peux pas manipuler les noms des variables, il faut travailler avec des tableaux ("table" en LUA) Exemple de code, à tester : local ids = { [1] = 1234, [2] = 4567, } for _, ID_device in ipairs(ids) print("Device under analysis :", ID_device) local value = hub.getValue(ID_device, "power") print("value_" .. ID_device .. " :", value) end
TitiXsi Posté(e) le 8 février Signaler Posté(e) le 8 février C'est évidemment plus simple... la non évaluation des variables string c'est une spécificité LUA ou un bloquage de fibaro qui n'a pas porté la feature ?
Lazer Posté(e) le 8 février Signaler Posté(e) le 8 février (modifié) Ce n'est ni lié à Fibaro, ni au LUA, mais au mode de fonctionnement des compilateurs de langage de programmation en général. Tu connais un language de programmation où tu peux manipuler le nom d'une variable et en évaluer son contenu ? En LUA, ce que tu peux manipuler, ce sont les noms (sous forme de string) des index des tableaux. J'aurais pu t'écrire un bout de code en sens là d'ailleurs, mais c'était plus lourd que la solution très basique que je t'ai proposé. D'ailleurs ta question n'a rien à voir avec les QuickApp directement, mais plutôt aux possibilités du langage LUA en général. Modifié le 8 février par Lazer
TitiXsi Posté(e) le 8 février Signaler Posté(e) le 8 février C'est évidemment plus simple... la non évaluation des variables string c'est une spécificité LUA ou un bloquage de fibaro qui n'a pas porté la feature ?
TitiXsi Posté(e) le 8 février Signaler Posté(e) le 8 février (modifié) il y a 18 minutes, Lazer a dit : Tu connais un language de programmation où tu peux manipuler le nom d'une variable et en évaluer son contenu ? Le TCL avec la commande eval, tous les Shells notamment le Cshell ou le Tcsh avec le back quote ` Modifié le 8 février par TitiXsi
Messages recommandés