henri-allauch Posté(e) le 8 avril 2021 Auteur Signaler Posté(e) le 8 avril 2021 ce matin je croyais que cette fonction était OK function SetwakeUpTime( IdDevice ) local data = { properties={ wakeUpTime = 21600 }, } api.put("/callAction/".. IdDevice, data) end local IdDevice = 253 SetwakeUpTime(IdDevice) En fait il n'en est rien, c'est la commande suivante qui a bien modifié le wakeUpTime http://MyUser:MyPassword@192.168.1.53/api/callAction?deviceID=253&name=setProperty&arg1=wakeUpTime&arg2=8000 Je ne trouve pas mon erreur dans la fonction avec le api.put ( qui retourne nill si je teste le status et la réponse )
jjacques68 Posté(e) le 9 avril 2021 Signaler Posté(e) le 9 avril 2021 il faut récupérer, dans ta variable data, le contenu json du device avec un api.get(), avant de faire le put... oula je sais pas si je me suis fait comprendre là
henri-allauch Posté(e) le 9 avril 2021 Auteur Signaler Posté(e) le 9 avril 2021 il y a une heure, jjacques68 a dit : oula je sais pas si je me suis fait comprendre là Pas trop mais pas grave j'ai fait autrement (http request ) mais ça ne me plaid pas mais je ne comprend pas. dans le json on est bien dans properties et wakeUptime De plus ce parametre semble accessible par l'onglet avancé du device ( intervalle de réveil ) à priori
jjacques68 Posté(e) le 9 avril 2021 Signaler Posté(e) le 9 avril 2021 (modifié) un truc dans le genre : data = api.get("/device/MON_ID") data.properties.wakeupTime = xxxxxx api.put("/device/MON_ID", data) je l'utilise ici : EDIT : sans oublier de faire le r2veil du module... Modifié le 9 avril 2021 par jjacques68 1
henri-allauch Posté(e) le 10 avril 2021 Auteur Signaler Posté(e) le 10 avril 2021 (modifié) @jjacques68 merci je me suis inspiré de la méthode de ton QA le résultat est OK Lorsqu'on utilise une variable ex: ID_monAppareil := 123 et qu'on va la retrouver dans plusieurs scène ou QA Qu'elle stratégie utiliser pour que ce soit uniforme et pour les retrouver facilement ? Perso j'ai une liste dans un QA (Reference) et je copie manuellement le self.ID_monAppareil = 123 dans les QA où j'en ai besoin. J'avais essayé d'automatiser cela à l'init du QA mais sans succès . Modifié le 10 avril 2021 par henri-allauch
jjacques68 Posté(e) le 10 avril 2021 Signaler Posté(e) le 10 avril 2021 pas sûr d'avoir compris... si c'est pour récupérer l'id du QA en cours d'utilisation, tu fais self.id sinon y a toujours les VG "à l'ancienne". mais je ne les utilises quasi plus du tout. si tu as un exemple à donner, on pourra y réfléchir...
henri-allauch Posté(e) le 10 avril 2021 Auteur Signaler Posté(e) le 10 avril 2021 Soit un device 255 c'est pas parlant pour savoir qui c'est je declare self.Id_LumièreJardinDevant = 255 dans le init D'un QA pour l'utiliser dans celui-ci dans plusieurs fonction : par exemple if ( id == self.Id_LumièreJardinDevant ) then ... Pas de soucis. Si j'ai plusieurs QA qui utilise ce device, je fais de même dans chaque QA Pas de soucis non plus C'est répétitif mais je n'ai pas de solution pour le déclarer d'une manière globale et le charger en cas de besoin (trop de devices pour les mettre en VG) Mais je cherche à être strict pour pouvoir si besoin changer la valeur du device en cas de remplacement de celui-ci ( donc changement d'ID ) et retrouver facilement tous les QA qui utilisent self.Id_LumièreJardinDevant = 255 Donc j'ai une liste disons de référence et je fait des couper coller dans tous les devices qui utilise Id_LumièreJardinDevant
jjacques68 Posté(e) le 10 avril 2021 Signaler Posté(e) le 10 avril 2021 ah ok ! là c'est clair... ben là j'ai pas d'idée sous le coude Ne vaudrait-il pas regrouper les QA pour que tous ceux qui utilisent ce device ne fassent qu'un ?
henri-allauch Posté(e) le 22 avril 2021 Auteur Signaler Posté(e) le 22 avril 2021 (modifié) J'ai de temps en temps des actions doublées dans le traitement du refreshStates ( méthode issue des exemple ci -dessus et du forum officiel ) Je ne comprend pas pourquoi, j'ai donc simplifié le Qa sans traiter les évenements, il s'avère que je traite plusieurs fois la même sortie de la requête HTTP refreshStates ( le meme lastRefresh ) local function pollRefresh() --self:warning("<font color=green>", "Request with lastRefresh: ", lastRefresh ,"</font>") --*****Si on ajoute ce warning tout va bien***** local stat,res = self.http:request("http://127.0.0.1:11111/api/refreshStates?last=" .. lastRefresh, { success = function(res) local states = json.decode(res.data) if states then if lastRefresh == states.last then self:warning("<font color=yellow>", "lastRefresh: ", lastRefresh , " states.last : ", states.last ,"</font>") end lastRefresh=states.last if states.events and #states.events > 0 then checkEvents(states.last) end -- Henri last pour debug only) end end, error = function(res) self:error("Error : refreshStates : " .. res) end, }) end --pollRefresh Dans l'exemple et le QA joint, si je valide le warning ( ligne 26 ) avant la req Http, tout va bien : on voit en vert les req avec le lastrefresh qui évolue , et s'il y a lieu on part dans le checkevent() Si j'enlève ce warning on voit en jaune je résultat du warning (ligne 32 ) le state.last issu de la req est = à l'ancien et on part dans checkevent() donc plusieurs fois avec les mêmes évenements. Si je passe l'interval à 2 secondes je diminue ou supprime ce problème ( coome en ajoutant le warning avant la req ) Il y a un pb de timing que je ne maitrise pas. Cela explique peut être mon post un peu plus haut qui signalait un plantage acev un polling à 0 j'ai besoin d'un expert ... QA refreshStates.lua Modifié le 22 avril 2021 par henri-allauch
jang Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 (modifié) il y a 49 minutes, henri-allauch a dit : Is this better? math.randomseed(os.time()) local urlTail = "&lang=en&rand="..math.random(2000,4000).."&logs=false" local lastRefresh = 0 local function pollRefresh() --self:warning("<font color=green>", "Request with lastRefresh: ", lastRefresh ,"</font>") --*****Si on ajoute ce warning tout va bien***** local stat,res = self.http:request("http://127.0.0.1:11111/api/refreshStates?last=" .. lastRefresh..urlTail, { success = function(res) local states = res.status==200 and json.decode(res.data) if states then if lastRefresh == states.last then self:warning("<font color=yellow>", "lastRefresh: ", lastRefresh , " states.last : ", states.last ,"</font>") end lastRefresh=states.last if states.events and #states.events > 0 then checkEvents(states.last) end -- Henri last pour debug only) end end, error = function(res) self:error("Error : refreshStates : " .. res) end, }) end --pollRefresh Modifié le 22 avril 2021 par jang 1
henri-allauch Posté(e) le 22 avril 2021 Auteur Signaler Posté(e) le 22 avril 2021 Thank's but it's the same PB for example 119643 is processed more than once
jjacques68 Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 hmm... je ne vois pas l'instruction qui fait le bouclage (setTimeout). Donc tu dois l'avoir à un autre endroit. Et je me demande si les soucis viennent pas de là. Tu as peut-être une sorte de désynchronisation entre la fonction qui appelle PollRefresh() et le traitement des instructions. ça va te chambouler pas mal le code mais : Essayes de mettre la relance de la boucle tout à la fin du succes. Et du coup aussi tout à la fin du error. C'est comme ça que j'ai fait chez moi. Tout est dans le succes(), j'appelle telle ou telle fonction suivant mes conditions.
henri-allauch Posté(e) le 22 avril 2021 Auteur Signaler Posté(e) le 22 avril 2021 @jjacques68 il n'y a pas de setTimeout, c'est le setinterval qui doit lancer la boucle chaque seconde et il le fait. Mais comme toi je pense à un desynchro J'ai regardé dans GEA la méthode de @Lazer et j'ai fait un mini QA ( donc là il y a setTimeout ) Et .... je n'ai pas le problème, avec ou sans warning de trace J'aimerai avant de modifier définitivement ma boucle initiale qui malgré tout fonctionne ""Presque bien " ton avis et celui de @lazer s'il a une minute .. ou 2 function QuickApp:onInit() __TAG = "TEST-STYLE GEA" .. plugin.mainDeviceId self:trace("") self:trace("QuickApp TEST-STYLE GEA - Initialization") self:trace("") self.refreshInterval = 1000 -- durée en millisecondes self.http = net.HTTPClient() self:start() end function QuickApp:start() -- Initialisation local lastRefresh = 0 -- Boucle d'attente d'événements instantanés local function loop() local stat,res = self.http:request("http://127.0.0.1:11111/api/refreshStates?last=" .. lastRefresh, { success = function(res) local states = json.decode(res.data) if type(states) == "table" then if states.last == lastRefresh then self:warning("<font color=red>", "ATTENTION -> lastRefresh : ", lastRefresh, "states.last : ", states.last ,"</font>") end --self:warning("<font color=green>", "OK -> lastRefresh : ", lastRefresh, "states.last : ", states.last ,"</font>") lastRefresh = states.last or 0 self:traitement(lastRefresh) end setTimeout(loop, self.refreshInterval) end, error = function(res) self:error("Error : refreshStates : " .. res) setTimeout(loop, 2 * self.refreshInterval) end, }) end self:warning("ICI Start Loop") loop() end function QuickApp:traitement(last) self:warning("<font color=yellow>" , "traitement(last) :", last, "</font>") end Style GEA.lua
Lazer Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 (modifié) C'est vrai ça... bien vu @jjacques68 @henri-allauch Du coup je suppose que tu utilises setInterval(), à mon avis ce n'est pas la bonne méthode. Car si le http.request() met plus de temps à répondre que ton intervalle => tu as les événements en double Perso je fais un setTimeout() dans les callbacks de http.request() (success() et error()) qui se rappelle lui-même à chaque boucle (avec un délai de 100 ms paramétrable). Normalement impossible d'avoir des events en double avec cette technique, car on est certain à la prochaine exécution de http.request() qu'on a bien pris en compte la dernière valeur connue de states.last Remarque de fond : d'où l'intérêt quand on demande de l'aide sur le forum de donner un maximum d'information, à savoir tout le code qui entoure la fonction qui pose problème, car c'est souvent le contexte qui pose problème plus que la syntaxe en elle-même. EDIT : @henri tu as répondu entre temps et tu confirmes exactement ce que je dit Modifié le 22 avril 2021 par Lazer 1
henri-allauch Posté(e) le 22 avril 2021 Auteur Signaler Posté(e) le 22 avril 2021 J'ai galéré pour le mettre en évidence car la mise en place de trace modifie les timing et l'erreur n'est plus visible. Je vais donc mettre en place la méthode avec setTimeout () ... à tête reposée. Pour l'histoire c'est à la migration de mon dernier device (une télécommande figaro) que j'ai ressenti les doubles évènements C'est le seul device ( dans mon cas) qui utile le CentralSceneEvent pour passer la Key et ses attributs. merci @jjacques68 @Lazer et @jang de vos conseils 1
jang Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 (modifié) 2 hours ago Lazer said: It's true that ... well seen @ jjacques68 @ henri-allauch So I guess you are using setInterval (), in my opinion this is not the right method. Because if the http.request () takes longer to respond than your interval => you have duplicate events Personally I do a setTimeout () in the callbacks of http.request () (success () and error ()) which remembers itself at each loop (with a configurable 100 ms delay). Normally impossible to have duplicate events with this technique, because you are certain the next time you run http.request () that you have taken into account the last known value of states.last Substantive remark: hence the interest when asking for help on the forum to give as much information as possible, namely all the code surrounding the function that poses a problem, because it is often the context that poses problem more than the syntax itself. EDIT: @henri you replied in the meantime and you confirm exactly what I said @ Lazer is right. I didn't notice the setInterval. Yes, the response time can vary depending if there are events available. ... and your requests "run over" each other. Modifié le 22 avril 2021 par jang 1
jjacques68 Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 t'es pas obligé de créer la fonction loop(). Dans les setTimeout, rappelles directement self:start() 1
Lazer Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 Non parce que ça va remettre lastRefresh = 0 C'est bien loop() qu'il faut appeler dans l'exemple du dessus. 1
jang Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 Il y a 7 heures, henri-allauch a dit : From time to time I have doubled actions in the processing of the refreshStates (method from the above examples and from the official forum) I don't understand why, so I simplified the Qa without processing the events, it turns out that I process the same output of the refreshStates HTTP request several times (the same lastRefresh) The Fibaro forum 'HC3 QuickApps coding - tips and tricks" have ~1200 posts starting February 2020. I wouldn't use any code before August 2020 - we have learnt a lot the last 6 months... 1 1
jjacques68 Posté(e) le 22 avril 2021 Signaler Posté(e) le 22 avril 2021 il y a une heure, Lazer a dit : Non parce que ça va remettre lastRefresh = 0 mince, avais pas fait gaffe à ça, désolé ...
henri-allauch Posté(e) le 24 avril 2021 Auteur Signaler Posté(e) le 24 avril 2021 Et comme disait Robert Lamoureux, ....... et le canard était toujours vivant Après avoir modifié mon code avec les setTimeout hier, j'ai toujours (dans le QA complet ) à la sortie de la requête refreshStates, des states.last égales au last de la requête précédente Certes moins nombreuses, mais autour de 10 à 20 par heure pour des cycles à 1 secondes. J'ai fait plein d'essais avant de reposter ici / augmentation du cycle a 1,5 secondes diminution à 0,1 secondes, il y en a toujours. Ajout de timer pour le net.hppClient Idem Sur un essai en code réduit, il me semble que si je supprime le traitement checkEvents lancé si succes, je n'ai plus ce problème. Si je comprend bien dans GEA, sur succes la recherche des évenements est en partie réalisé dans le on succes, ce qui fait que la requête refreshStates suivante est lancée après ce traitement. Alors que dans mon cas sur succes j'appelle la fonction checkEvents qui a son tour va appeler event ... donc la requête refreshStates suivante est lancés en // de ces traitements. Le problème est peut être là ??? je vais continuer mais ??? Ma boucle actuelle et en piece jointe le Qa complet au cas ou quelqu'un a une idée function QuickApp:start() -- Initialisation local lastRefresh = 0 math.randomseed(os.time()) local urlTail = "&lang=en&rand="..math.random(2000,4000).."&logs=false" -- Boucle d'attente d'événements instantanés local function loop() local stat,res = self.http:request("http://127.0.0.1:11111/api/refreshStates?last=" .. lastRefresh ..urlTail, { success=function(res) local states = res.status == 200 and json.decode(res.data) if states then if states.last == lastRefresh then self:warning("<font color=red>", "ATTENTION -> lastRefresh : ", lastRefresh, "states.last : ", states.last ,"</font>") end --self:warning("<font color=green>", "OK -> lastRefresh : ", lastRefresh, "states.last : ", states.last ,"</font>") lastRefresh=states.last if states.events and #states.events>0 then checkEvents(states.events) end end setTimeout(loop, self.refreshInterval) end, error = function(res) self:error("Error : refreshStates : " .. res) setTimeout(loop, 2 * self.refreshInterval) end, }) end -- Lancement initial de la boucle loop() end QA Complet.lua
jjacques68 Posté(e) le 24 avril 2021 Signaler Posté(e) le 24 avril 2021 (modifié) ton code se rapproche du mien... enlèves voir "urlTail" de l'url pour voir ce que ça donne !? EDIT : je viens de me rendre compte que j'ai dans l'url en plus du "last" : &logs=true Modifié le 24 avril 2021 par jjacques68
jjacques68 Posté(e) le 24 avril 2021 Signaler Posté(e) le 24 avril 2021 minute là !! Moi aussi j'ai des trames en doubles visiblement !! Je viens de mettre une conditions qui m'affiche un warning si le last=lastResfresh !! Mais j'ai jamais constaté que ça pouvais poser problème !!??
jjacques68 Posté(e) le 24 avril 2021 Signaler Posté(e) le 24 avril 2021 Ce serait pas normal ? Le "last" ne resterait pas identique si pas d'évènements ? J'ai l'impression que j'en ai que quand rien ne se passe ?!
Lazer Posté(e) le 24 avril 2021 Signaler Posté(e) le 24 avril 2021 (modifié) last=lastResfresh peut arriver par exemple si aucun nouvel événement durant la temps d'attente de la requête le problème n'est pas d'avoir last=lastResfresh mais d'avoir des événements en double, ce qui n'est pas censé arriver EDIT : bon bah voilà @jjacques68 tu fais les questions/réponses tout seul Modifié le 24 avril 2021 par Lazer
Messages recommandés