Aller au contenu
henri-allauch

UN petit coup de main SVP

Recommended Posts

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 )

 

Partager ce message


Lien à poster
Partager sur d’autres sites

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à :) 

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a une heure, jjacques68 a dit :

oula je sais pas si je me suis fait comprendre

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

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites

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é par jjacques68
  • Thanks 1

Partager ce message


Lien à poster
Partager sur d’autres sites

@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é par henri-allauch

Partager ce message


Lien à poster
Partager sur d’autres sites

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... :) 

Partager ce message


Lien à poster
Partager sur d’autres sites

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

 

Partager ce message


Lien à poster
Partager sur d’autres sites

ah ok ! là c'est clair...

ben là j'ai pas d'idée sous le coude :15:

Ne vaudrait-il pas regrouper les QA pour que tous ceux qui utilisent ce device ne fassent qu'un ?

 

Partager ce message


Lien à poster
Partager sur d’autres sites

 

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

Trace avec Erreur.png

Trace Normale.png

Modifié par henri-allauch

Partager ce message


Lien à poster
Partager sur d’autres sites
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é par jang
  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

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.

Partager ce message


Lien à poster
Partager sur d’autres sites

@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

Partager ce message


Lien à poster
Partager sur d’autres sites

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é par Lazer
  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

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

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites
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é par jang
  • Thanks 1

Partager ce message


Lien à poster
Partager sur d’autres sites

t'es pas obligé de créer la fonction loop().

Dans les setTimeout, rappelles directement self:start()

  • Thanks 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Non parce que ça va remettre lastRefresh = 0

C'est bien loop() qu'il faut appeler dans l'exemple du dessus.

  • Thanks 1

Partager ce message


Lien à poster
Partager sur d’autres sites
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... ;)

  • Like 1
  • Thanks 1

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a une heure, Lazer a dit :

Non parce que ça va remettre lastRefresh = 0

mince, avais pas fait gaffe à ça, désolé ...

Partager ce message


Lien à poster
Partager sur d’autres sites

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

Partager ce message


Lien à poster
Partager sur d’autres sites

:15::15:

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é par jjacques68

Partager ce message


Lien à poster
Partager sur d’autres sites

:police:

 

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 !!

:15:

Mais j'ai jamais constaté que ça pouvais poser problème !!??

 

Partager ce message


Lien à poster
Partager sur d’autres sites

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 ?!

Partager ce message


Lien à poster
Partager sur d’autres sites

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é par Lazer

Partager ce message


Lien à poster
Partager sur d’autres sites

×