Aller au contenu

Messages recommandés

Posté(e)

Bonjour,

Je bloque sur ce bout de code. Et il me semble que c'est ok, mais apparemment non ...

    http:request(url, {
                        success = function(response)
                            if response.status == 200 then
                                self:trace("OK, réponse : ".. response.data)
                                local resp = json.decode(response.data)
                                self:trace("resp = "..tostring(resp))
                                local id = resp.nukiId
                                self:trace("nukiId = ".. tostring(id))
                          else

je cherche à extraire le nukiId de la response.

et voici le log :


[27.07.2022] [18:47:57] [DEBUG] [QUICKAPP258]: onInit
[27.07.2022] [18:47:57] [DEBUG] [QUICKAPP258]: State
[27.07.2022] [18:47:57] [TRACE] [QUICKAPP258]: url = http://192.168.1.xxx:8080/list?token=zzzzzz
[27.07.2022] [18:47:58] [TRACE] [QUICKAPP258]: OK, réponse : [{"deviceType": 0, "nukiId": 184981569, "name": "Entrée", "firmwareVersion": "1.14.1", "lastKnownState": {"mode": 2, "state": 3, "stateName": "unlocked", "batteryCritical": false, "batteryCharging": false, "batteryChargeState": 32, "keypadBatteryCritical": false, "timestamp": "2022-07-27T09:31:33+00:00"}}]
[27.07.2022] [18:47:58] [TRACE] [QUICKAPP258]: resp = table: 0x3f1e6a30
[27.07.2022] [18:47:58] [TRACE] [QUICKAPP258]: nukiId = nil

où est mon erreur ?

Merci pour vos yeux et votre cerveau.

Posté(e)

il y a un truc vraiment étrange

Dans ma fonction il n'rxécute pas les instructions après le 

    http:request(url, {
                        success = function(response)
  ...
    				  }
                    )

voici mon code "complet" : je souhaite traiter resp ensuite.

    http:request(url, {
                        success = function(response)
                            if response.status == 200 then
                                self:trace("OK, réponse : ".. response.data)
                                resp = json.decode(response.data)
                            else
                                self:error("Erreur : réponse avec statut = " .. tostring(response.status))
                            end
                        end,
                        error = function(err)
                            self:error("Erreur : " .. err)
                        end,
                        options = {
                            method = 'GET'
                                  }
                       }
                    )
    local id = resp[1].nukiId
    self:trace("nukiId = ".. tostring(id))

Merci

Posté(e)

Merci, je confirme que dans le debug, je vois l'instruction qui est après mon call http avant le résultat.

 

Il doit surement y avoir une bonne raison à cela, mais je ne la vois pas.

Pourquoi exécuter des actions alors que la précédente n'est pas finie ???

 

Je vais regarder ton lien, il y aura sûrement une réponse à mon questionnement,  mais d'ici là, je considère cela comme TRES stupide et profondément illogique.

Posté(e)

Non ce n'est pas très stupide, au contraire c'est bien plus logique ainsi, et surtout très puissant.

Mais pas évident à assimiler au début.

Commence par lire le lien, tout est expliqué.

Posté(e)

Comme le dit lazer il faut changer ça méthode pour écrire le code
Et surtout ne pas utiliser le sleep
Pour que la commande s'exécute apparaît il faut la mettre dans une fonction timeout()

Envoyé de mon BLA-L29 en utilisant Tapatalk

Posté(e)

j'avais bien l'intention de lire le lien, mais c'est vrai, JE suis stupide, pourquoi faire simple, quand on peut faire compliqué ? :98::98:

  • Like 1
Posté(e)

Ce n'est pas une question de stupidité

C'est juste que le code s'exécute differament. Donc ça change les vieilles habitudes

Envoyé de mon BLA-L29 en utilisant Tapatalk

Posté(e)
Il y a 4 heures, Lazer a dit :

Non ce n'est pas très stupide, au contraire c'est bien plus logique ainsi, et surtout très puissant.

Mais pas évident à assimiler au début.

Commence par lire le lien, tout est expliqué.

j'ai lu ton topic, très instructif en effet.

en résumé : "fait comme on te dit de faire, sans discuter, ni essayer de comprendre pourquoi" => oui chef, de toute façon c'est comme ça.

Je n'ai toujours pas compris l'avantage :20:, si ce n'est de m'obliger à changer mes habitudes de vieux.

Posté(e)

@jojo ca peut être perturbant, mais c'est très puissant...  bon, après, c'est de la pure gestion asynchrone...   ca va te permettre par exemple lorsque tu fais appel à une fonction qui demande un certain temps de réponse (appel extérieur vers un device externe par exemple) de continuer une partie de ton code qui  n'est pas dépendante de ton code...  ce qui dépend de la réponse reçue lors de ton appel sera traité lorsque la réponse arrivera...  très logique en fait, etttt le reste peut être exécuté directement...  il y a plein de cas ou c'es très utile, et aujourd'hui dans "l'informatique" moderne on traite bienj souvent de cette manière plutôt qu'en simple séquentiel...  le top c'est le bus événementiel où ton code fait des choses, et parfois reçoit un évènement que tu traites ...  (bon, ok, je simplifie très fort :))...  mais comme cela a été dit, il faut juste oublier de penser comme avant et puis ca roule... ;) 

  • Like 1
  • Thanks 1
Posté(e)

If net.HTTPClient() was synchronous (returning the result immediately) it would have looked like

local success,res = net.HTTPClient():request("http://myurl",options)
if success then print(res) end

a little like in the old HC2 VDs. 

If the function takes other functions for success/error or callback it's a hint that the function is asynchronous. 

E.g. will return immediately and later call your functions when it is ready.

 

This is usually much more efficient if you have something else to do while you wait for the work to be completed.

...IF you have something else to do while you wait. Most code in the forums don't and a lot of beginners stumble on this.

 

Fibaro could have let us both have the cake and eat it, however Fibaro is not very "developer friendly".

With a few lines of code in the QA we could have had synchronous net.HTTPClient() 

and asynchronous setTimeout calls. If we wanted "parallel" net.HTTPClient() calls we would just call them in separate setTimeout functions.

Just look at the section "Your QA code" in the code below

QuickApp = {}

------------- Your QA code ------------

function QuickApp:ping() -- setTimeout loop logging "ping" every second
  self:debug("ping")
  setTimeout(function() self:ping() end,1000)
end

function QuickApp:onInit()
  self:debug("MyQA")
  setTimeout(function() self:ping() end,0) -- Start ping loop
  local success,res = net.HTTPClient():request("http://myurl") -- Run http request and wait for result
  if success==true then -- If success print result
    self:debug("Success:",res)
  end
end

------------- End ----------------------

local http = {}
net = { HTTPClient = function() return http end }
function http:request(url) -- Synchronous http call that respect other timers
  print("net.HTTPClient: Calling ",url,"-will take 5 seconds")
  local co = coroutine.running()
  setTimeout(function()
      print("net.HTTPClient: ready")
      coroutine.resume(co,true,"This is the result") -- We always succeed
    end,5000)
  return coroutine.yield()
end

local timers = {}
function setTimeout(f,t)
  table.insert(timers,{coroutine.wrap(f),t/1000+os.time()})
  table.sort(timers,function(a,b) return a[2] <= b[2] end)
end

if QuickApp.onInit then
  function QuickApp:debug(...) print(os.date("%c"),...) end
  setTimeout(function() QuickApp:onInit() end,0)
end

while true do
  local t = table.remove(timers,1)
  while t[2] > os.time() do  end
  t[1]()
end

It will run the "ping" loop while the net.HTTPClient() call waits for its result. We can write much more "natural" code and everyone would be more happy, and we would see less buggy code...

However, it doesn't work on the HC3 as Fibaro in its infinite wisdom has decided to disable coroutines that is one of the biggest features of Lua. (You can try to run the example in any other "full" Lua environment to see it in action...)

'coroutines', in short, allow us to suspend execution of the code in the middle of your function (yield) and then later "wake up" the function so that it continues to run from where it was suspended (resume).

In our code we let setTimeout wrap the function in a coroutine so that the function can be suspended and resumed.
In the case above we suspend the net.HTTPClient() call, and then when it's ready (5s later) we wake it up so the function can return the result to the waiting caller.

local success,res = net.HTTPClient():request("http://myurl")

So, Lua is a very powerful language but we are unfortunately only allowed to use a small part of it...

  • Like 2
  • Thanks 1
Posté(e)

Thank you @jang for this detailed info.

As I'm not a developper, I'll to re-read your post 10 times to start understanding it , but one day I will understand ...

Posté(e) (modifié)

Don't lose any sleep over the post. The simple take-away was that Fibaro could have let us have both synchronous net.HTTPClient calls and asynchronous setTimeout, that would have made it easier for developers - and that with just a few lines of code. (then to prove it I gave an implementation, but that may be a bit advanced to follow, and put you to sleep  ;))

Modifié par jang
  • Thanks 1
×
×
  • Créer...