Aller au contenu

Messages recommandés

Posté(e)

Hello !

 

Petite question :

 

est-il possible qu'un QA renvoie une valeur suite à son appelle ?

 

Voici un exemple tout bête :

function QuickApp:MyFunction()
	return "toto"
end

 

et voici son appel

MonRetour = fibaro.call(xx, "MyFunction)

 

Mais visiblement ça marche pas :( 

 

Alors pour des retours de type :

 

  • boolean, il suffit d'utiliser un QA de type binarySensor/Switch
  • numérique, il faut utiliser un QA de type multilevelSensor/Switch
  • string ?????

 

J'ai bien tenté d'utiliser des QA de type générique, mais ils ne proposent pas la propriété "value" !

 

Posté(e)

C’est dans le backlog mais pas de retour de Fibaro sur cette demande.

Je te confirme donc que cela n’est pas à ma connaissance faisable et que clairement cela manque !
L’astuce pour faire sans pour le moment cette de faire le retour dans une variable globale puis de mettre un trigger sur cette variable dans la scène, comme cela la scène reçoit le retour dès mis à disposition ;) je n’ai pas trouvé mieux pour le moment en matière de performance et efficacité.
Il faut encore coder pour contourner cela peut devenir lassant... et surtout de plus en plus difficile à maintenir.


Envoyé de mon iPhone en utilisant Tapatalk

Posté(e) (modifié)
On 3/24/2020 at 6:02 PM, jjacques68 said:

Well, go for a VG then :(

It is kind of a shame ...

Thank you !!

 

Here's a way to make synchronous calls between QA - and it's pretty quick.

QA server. plugin.mainDeviceId = 240---------------------------------------------------------- -------- -------- --------

function  foo (a, b)  return  a + b  end --- fun test 

-- call = {callerID = <id>, callVar = <string>, fun = <string>, args = <table>}
function QuickApp :  RPC (call)
    local  res = _G [call.fun]  and  {pcall (_G [call.fun], table.unpack (call.args))}  or  { false , "No such function" }
    fibaro.setGlobalVariable (call.var, json.encode (res))
end
 
function QuickApp : onInit ()
    self: debug ( "RPC server" , plugin.mainDeviceId)
end
 

 

QA Client:

---------------------------------------------------------- -------- -------- -------------

local function  rpc (id, timeout, fun, ...) 
    local  v =  "RPC" ..tostring ({}): sub ( 10 )
    api.post ( "/ globalVariables" , {name = v})
    fibaro.call (id, "RPC" , {id = plugin.mainDeviceId, var = v, fun = fun, args = {...}})
    local  t, res = os.time () + timeout, { false , "timeout" }
    while  os.time () <= t  do 
        res = fibaro.getGlobalVariable (v) 
        print (type (res))
        if  res  and  res ~ =  "" then  res = json.decode (res)  break end  
    end
    api.delete ( "/ globalVariables /" ..v)
   if  res [ 1 ]  then return  select ( 2 , table.unpack (res))  else  error (res [ 2 ])  end 
end

local function  rpcFun (id, timeout, fun)  return function (...)  return  rpc (id, timeout, fun, ...)  end end   
 
function QuickApp : onInit ()
    self: debug ( "onInit" , plugin.mainDeviceId)
    local  foo = rpcFun ( 240 , 5 , "foo" )
    for  i = 1 , 10 do  print (foo ( 8 , i))  end 
end
---------------------------------------------------------- -------- -------- -------- -------------
Modifié par jang
  • Like 1
Posté(e) (modifié)

I'm giving up. I can't paste code in this forum  I think I succeeded.

Modifié par jang
  • Like 1
  • Thanks 1
Posté(e) (modifié)

I try to use a part of your method with another code, to do something else, but it doesn't work and I don't understand the result :

 

I open a socket to Wireless device throught 23 port and I must receive a response...

 

here is a part of the main code :

 

-- init of Variable QA
self:setVariable("Result", "toto")

-- open connection to the device
self.sock:connect(self:getVariable("IP"), 23, {  

    success = function(result)     
      self:debug("SUCCES CONNECTION")

      --read response
      self:Read()

      --wait response (3 s)...
      Timeout = os.time() + 3
      while os.time() < Timeout do 
        res = self:getVariable("Result")
        self:debug("VARIABLE = "..res)
        if res and res ~= "toto" then break end
        fibaro.sleep(1000)   
      end

      self:debug("END LOOP - "..res)            
    end,

 

here is the function Read() : in the same QA

 

function QuickApp:Read()
    self:debug("START READ...")
    self.sock:read({
        success = function(result)
            self:setVariable("Result", result)
            self:debug("END READ - "..result)
        end,
        error = function(err) self:debug("READ ERROR - "..err) end
    })
end

and now, the result in debug console :

 

[DEBUG] 26.03.2020 08:47:35: onInit
[DEBUG] 26.03.2020 08:47:37: onUIEvent: {"eventType":"onReleased","deviceId":133,"values":[null],"elementName":"button1"}
[DEBUG] 26.03.2020 08:47:37: SUCCES CONNECTION
[DEBUG] 26.03.2020 08:47:37: START READ...
[DEBUG] 26.03.2020 08:47:37: VARIABLE = toto
[DEBUG] 26.03.2020 08:47:38: VARIABLE = toto
[DEBUG] 26.03.2020 08:47:39: VARIABLE = toto
[DEBUG] 26.03.2020 08:47:40: END LOOP - toto
[DEBUG] 26.03.2020 08:59:08: END READ - ������!���� login:

I don't understand why, "END READ - OK" is in the end !!!

 

it should be before "END LOOP" !!!!

and the result should be normally : "������!���� login:" 

 

I have the impression that, "self.sock:read" is blocked during the loop in the main.

And the variable is not update.

 

I try with to call Read() with a setTimeout(), but it's worse...

I try with a Global Variable, but it's the same result...

I try with a variable declared in the QA with self.xxx, but same...

 

do you have an idea ?

 

edit :

 

if I delete the loop : it's ok, but maybe I don't receive the response in times...

I would like to keep the timeout loop...

 

but how ?

 

[DEBUG] 26.03.2020 09:01:53: SUCCES CONNECTION
[DEBUG] 26.03.2020 09:01:53: START READ...
[DEBUG] 26.03.2020 09:01:53: END READ - ������!���� login:

 

Modifié par jjacques68
Posté(e)

I think, I find the solution :

 

I had to put the whole loop in a setTimeout

 

-- init of Variable QA
self:setVariable("Result", "toto")

-- open connection to the device
self.sock:connect(self:getVariable("IP"), 23, {  

    success = function(result)     
      self:debug("SUCCES CONNECTION")

      --read response
      self:Read()

      --wait response
      fibaro.setTimeout(10, 
        function() 
          --wait response (3 s)...
          Timeout = os.time() + 3
          while os.time() < Timeout do 
            res = self:getVariable("Result")
            --self:debug("VARIABLE = "..res)
            if res and res ~= "toto" then break end
            fibaro.sleep(1000)   
          end

          self:debug("END LOOP - "..res)
        end)
    end,  

and the debug

 

[DEBUG] 26.03.2020 09:14:47: onUIEvent: {"elementName":"button1","eventType":"onReleased","deviceId":133,"values":[null]}
[DEBUG] 26.03.2020 09:14:47: SUCCES CONNECTION
[DEBUG] 26.03.2020 09:14:47: START READ...
[DEBUG] 26.03.2020 09:14:47: END LOOP - ������!���� login:

 

Posté(e) (modifié)
2 hours ago, jjacques68 said:

I think, I find the solution :

 

I had to put the whole loop in a setTimeout



 

 

Unfortunately, you were just lucky that the answer came during the 10ms of your setTimeout.

When you enter the while-loop nothing else will run in the same QA.

In fact, nothing happens in parallel in a QA, not call-backs, not calls to QuickApp: function etc. You need to constantly give time to other parts of your code with setTimeout.

My example works because it's between two different QAs.

 

If you use it within the same QA you need to use callbacks and setTimeout loop - not as elegant / simple.

Ex. (Server same)

Customer:

local function rpc(callback,id,timeout,fun,...)
    local v,args = "RPC"..tostring({}):sub(10),{...}
    api.post("/globalVariables",{name=v})
    setTimeout(function() fibaro.call(id,"RPC",{id=plugin.mainDeviceId,var=v,fun=fun,args=args}) end,0)
    local t,res=os.time()+timeout
    local function loop()
       if os.time()<=t then 
           local res = fibaro.getGlobalVariable(v) 
           if res and res~= "" then 
               api.delete("/globalVariables/"..v) 
               res = json.decode(res)
               if res[1] then
                  callback(select(2,table.unpack(res)))
               else print("RPC error:"..res[2])  end
           else setTimeout(loop,10) end
       else 
          api.delete("/globalVariables/"..v)
          print("RPC Timeout:"..fun)  
       end
    end
    loop()
end

local function rpcFun(id,timeout,fun) return function(cb,...) return rpc(cb,id,timeout,fun,...) end end 

function QuickApp:onInit()
    self:debug("onInit ",plugin.mainDeviceId)
    local foo = rpcFun(240,5,"foo")
    for i=1,10 do foo(print,8,i) end
end

 

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