-
Compteur de contenus
206 -
Inscription
-
Dernière visite
-
Jours gagnés
41
Tout ce qui a été posté par jang
-
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
-
In northern Sweden, sunrise is before 2:00 in the summer...
-
print(_VERSION) hour = 1 hour = hour + 1 print ("hour:".. hour) hour = hour + "1" print ("hour:".. hour) a = 1 b = 2.0 print("Type a:",type(a)) print("Type b:",type(b)) print("math.type a:",math.type(a)) print("math.type b:",math.type(b)) a = 3.0 b = 3.1 print("tointeger a:",math.tointeger(a)) print("tointeger b:",math.tointeger(b)) Lua 5.3 hour:2 hour:3.0 Type a: number Type b: number math.type a: integer math.type b: float tointeger a: 3 tointeger b: nil http://www.lua.org/manual/5.3/manual.html#pdf-math.tointeger
-
No, and it's tricky also for Fibaro as it is between 2 different processes (each QA is its own process) This is one way to do it https://forum.fibaro.com/topic/49113-hc3-quickapps-coding-tips-and-tricks/?do=findComment&comment=207479 Client (unfortunately needs most code, but can be put in a "Library file") do local var,n = "RPC_"..plugin.mainDeviceId,0 api.post("/globalVariables",{name=var,value=""}) function rpc(id,fun,args,timeout) fibaro.setGlobalVariable(var,"") n = n + 1 fibaro.call(id,"RPC_CALL",var,n,fun,args) timeout = os.time()+(timeout or 3) while os.time() < timeout do local r = fibaro.getGlobalVariable(var) if r~="" then r = json.decode(r) if r[1] == n then if not r[2] then error(r[3],3) else return select(3,table.unpack(r)) end end end end error(string.format("RPC timeout %s:%d",fun,id),3) end end local function defineRemote(id, fun, timeout) _G[fun]=function(...) rpc(id, fun, {...}, timeout) end end function QuickApp:test() n=100 local t0 = os.clock() for i=1,n do foo(3,i) -- Remote call to QA 58 and function foo with args 3,i 100 times and calculate average time end print(string.format("Call time: %.3fms",((os.clock()-t0)*1000)/n)) end function QuickApp:onInit() self:debug("RPC") defineRemote(58,"foo") -- define remote function foo from QA 58 sel:test() end The "server" (with deviceID 58) that exports 'foo' is much simpler. In fact, all global functions in QA 58 can be called from remote. function QuickApp:RPC_CALL(var,n,fun,args) local res = {n,pcall(_G[fun],table.unpack(args))} fibaro.setGlobalVariable(var,json.encode(res)) end function foo(x,y) return x+y end -- Remote function The time it takes for a call is ~11.7ms, which is quite ok. [23.03.2021] [21:41:00] [DEBUG] [QUICKAPP57]: Call time: 11.757ms
-
Do we know that? I believe that in a normally loaded HC3 there are enough events to even it out (processing events/second). I.e you poll often and get few events each time or you poll less often and get many. In a light environment the request will hang waiting for new events taking no CPU.
-
If you use request ("http://127.0.0.1:11111/api/refreshStates?last=" ... you can poll with 0 delay. With refreshStates the trick is to efficiently map incoming refresh event to what what function/rule you want to call.
-
Yes, that's how I do it in EventRunner4 too. local uptime = api.get("/settings/info").serverStatus or 0 if os.time()-uptime < 30 then quickApp:post({type='se-start'}) end I have a post function that adds fake events to my refreshStates loop. Nice way to test functionality in the system too...
-
This is how I would tackle DST local events = { {time="02:00",action=function() print("02:00 Ding!") end}, {time="15:10",action=function() print("15:10 Ding!") end}, {time="21:03",action=function() print("21:03 Ding!") end}, } local function setUpDayEvents(self) local now=os.date("*t") now=60*60*now.hour+60*now.min+now.sec for _,e in ipairs(events) do local h,m=e.time:match("(%d+):(%d+)") local t = 60*60*tonumber(h)+60*tonumber(m) if t >= now then quickApp:debug("Schedule:"..e.time) setTimeout(e.action,1000*(t-now),e.time) end end end function intervalRunner(seconds,fun) local nxt local function loop() if fun()=='RESTARTED' then return end -- We still resturn after plugin.restart... nxt=nxt+seconds local a = setTimeout(loop,1000*(nxt-os.time())) end local t = (os.time() // seconds) * seconds nxt=t+seconds setTimeout(loop,1000*(nxt-os.time()-(seconds > 3600 and 3600 or 0))) end function QuickApp:onInit() quickApp = self setUpDayEvents() intervalRunner(24*60*60,setUpDayEvents) self:setVariable("DST",os.date("*t").isdst) intervalRunner(60*60,function() if os.date("*t").isdst ~= self:getVariable("DST") then self:debug("DST changed") plugin.restart() return "RESTARTED" end end) end -- rebooting the QA at DST... In this case it could be solved in other ways (with more code) - in more complicated QAs with many timers it may be the only approach... (DST in Sweden is on Sun Mar 28 03:00:00) Program starting as '"/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/lua.app/Contents/MacOS/lua53" -e "io.stdout:setvbuf('no')" "/var/folders/ft/sp22kj0d52l0f96grjcqwfyw0000gn/T/.kUBXRl"'. Program 'lua53' started in '/Users/erajgab/Dropbox/LUA/EventRunner/EventRunner' (pid: 65727). Debugging session started in '/Users/erajgab/Dropbox/LUA/EventRunner/EventRunner/'. [21.03.2021] [13:56:50] |SYS |: HC3 SDK v0.199 [21.03.2021] [13:56:50] |SYS |: Speeding 48 hours [21.03.2021] [13:56:50] |SYS |: Created Event server at 192.168.1.184:6872 [21.03.2021] [13:56:50] |SYS |: Created Terminal server at 192.168.1.184:6972 [27.03.2021] [10:00:00] |SYS |: Setting emulator time to Sat Mar 27 10:00:00 2021 [27.03.2021] [10:00:00] |LOG |: DST at Sun Mar 28 03:00:00 2021 [27.03.2021] [10:00:00] |SYS |: Setting speed to true [27.03.2021] [10:00:00] |-----|: ----------------------------------- Loading QuickApp 'My QA'... ----------------------------------- [27.03.2021] [10:00:00] |-----|: ---------------- QuickApp 'My QA', deviceID:999 started at Sat Mar 27 10:00:00 2021 ---------------- [27.03.2021] [10:00:00] [DEBUG] [QUICKAPP999]: Schedule:15:10 [27.03.2021] [10:00:00] [DEBUG] [QUICKAPP999]: Schedule:21:03 [27.03.2021] [10:00:00] |SDBG |: Incoming trigger:{"type":"DeviceCreatedEvent","data":{"id":999}} [27.03.2021] [15:10:00] [DEBUG] [QUICKAPP999]: 15:10 Ding! [27.03.2021] [21:03:00] [DEBUG] [QUICKAPP999]: 21:03 Ding! [28.03.2021] [00:00:00] [DEBUG] [QUICKAPP999]: Schedule:02:00 [28.03.2021] [00:00:00] [DEBUG] [QUICKAPP999]: Schedule:15:10 [28.03.2021] [00:00:00] [DEBUG] [QUICKAPP999]: Schedule:21:03 [28.03.2021] [03:00:00] [DEBUG] [QUICKAPP999]: 02:00 Ding! [28.03.2021] [03:00:00] [DEBUG] [QUICKAPP999]: DST changed [28.03.2021] [03:00:00] |SYS |: Restarting QA 999, timers=3, memory used 1298.5kB [28.03.2021] [03:00:00] |-----|: ---------------- QuickApp 'My QA', deviceID:999 started at Sun Mar 28 03:00:00 2021 ---------------- [28.03.2021] [03:00:00] [DEBUG] [QUICKAPP999]: Schedule:15:10 [28.03.2021] [03:00:00] [DEBUG] [QUICKAPP999]: Schedule:21:03 [28.03.2021] [14:00:00] |SDBG |: Incoming trigger:{"type":"DeviceModifiedEvent","data":{"id":999}} [28.03.2021] [15:10:00] [DEBUG] [QUICKAPP999]: 15:10 Ding! [28.03.2021] [21:03:00] [DEBUG] [QUICKAPP999]: 21:03 Ding! [29.03.2021] [01:00:00] [DEBUG] [QUICKAPP999]: Schedule:02:00 [29.03.2021] [01:00:00] [DEBUG] [QUICKAPP999]: Schedule:15:10 [29.03.2021] [01:00:00] [DEBUG] [QUICKAPP999]: Schedule:21:03 [29.03.2021] [02:00:00] [DEBUG] [QUICKAPP999]: 02:00 Ding! [29.03.2021] [10:00:00] |SYS |: Max time - exit Program completed in 0.84 seconds (pid: 65727). Debugging session completed (traced 0 instructions). Btw, even on the HC3 the code continues after the call to plugin.restart() until current function terminates - took me 3 hours to find the bug...:-)
-
Home exercise: How to survive daylight time savings?...
-
Example. local events = { {time="02:00",action=function() print("02:00 Ding!") end}, {time="15:10",action=function() print("15:10 Ding!") end}, {time="21:03",action=function() print("21:03 Ding!") end}, } local function setUpDayEvents() local now=os.date("*t") now=60*60*now.hour+60*now.min+now.sec for _,e in ipairs(events) do local h,m=e.time:match("(%d+):(%d+)") local t = 60*60*tonumber(h)+60*tonumber(m) if t >= now then setTimeout(e.action,1000*(t-now)) end end end function midnightRunner(fun) local nxt local function loop() print("Dong!") fun() nxt=nxt+24*60*60 -- Next midnight setTimeout(loop,1000*(nxt-os.time())) end local t = os.date("*t") t.hour,t.min,t.sec=0,0,0 -- Last midnight nxt=os.time(t)+24*60*60 -- Next midnight setTimeout(loop,1000*(nxt-os.time())) end function QuickApp:onInit() setUpDayEvents() -- When QA starts up midnightRunner(setUpDayEvents) -- Every midnight end Output: [20.03.2021] [08:09:02] |SYS |: HC3 SDK v0.199 [20.03.2021] [08:09:02] |SYS |: Speeding 24 hours [20.03.2021] [08:09:02] |SYS |: Created Event server at 192.168.1.184:6872 [20.03.2021] [08:09:02] |SYS |: Created Terminal server at 192.168.1.184:6972 [20.03.2021] [08:09:03] |SYS |: Setting speed to true [20.03.2021] [08:09:03] |LOG |: Polling HC3 for triggers every 2000ms [20.03.2021] [08:09:03] |-----|: ----------------------------------- Loading QuickApp 'My QA'... ----------------------------------- [20.03.2021] [08:09:03] |-----|: ---------------- QuickApp 'My QA', deviceID:999 started at Sat Mar 20 08:09:03 2021 ---------------- [20.03.2021] [08:09:03] |SDBG |: Incoming trigger:{"type":"DeviceCreatedEvent","data":{"id":999}} [20.03.2021] [15:10:00] [DEBUG] [QUICKAPP999]: 15:10 Ding! [20.03.2021] [21:03:00] [DEBUG] [QUICKAPP999]: 21:03 Ding! [21.03.2021] [00:00:00] [DEBUG] [QUICKAPP999]: Dong! [21.03.2021] [02:00:00] [DEBUG] [QUICKAPP999]: 02:00 Ding! [21.03.2021] [02:00:00] |SYS |: Max time - exit Program completed in 1.15 seconds (pid: 27233). Debugging session completed (traced 0 instructions). setTimeout can handle 24.8 days
-
This is not necessary anymore as we use http:request("http://127.0.0.1:11111/api/refreshStates?last=" ... that doesn't block other timers. It was necessary when we used api.get("/refreshStates...) that hanged and blocked timers if there were no events.
-
Your QA could emit customEvents for dawn and dusk etc., Scenes can react on customEvents.
-
Seulement le matin alors?
-
Need to add 'http://' prefix to url
-
You can do the same with Python, Perl whatever. However, to pull down the code you need to do it from outside the HC3. I think that is what henri-allauch was attempting.
-
Yes, but you have to run the code offline on PC/Mac (HC3 don't have io.*). Ex. using this
-
QuickApp - Chauffage Fil Pilote Qubino
jang a répondu à un(e) sujet de fredokl dans Quick App Developpeur
http://www.lua.org/manual/5.3/manual.html#3.4.1 "With the exception of exponentiation and float division, the arithmetic operators work as follows: If both operands are integers, the operation is performed over integers and the result is an integer. Otherwise, if both operands are numbers or strings that can be converted to numbers (see §3.4.3), then they are converted to floats, the operation is performed following the usual rules for floating-point arithmetic (usually the IEEE 754 standard), and the result is a float. Exponentiation and float division (/) always convert their operands to floats and the result is always a float. Exponentiation uses the ISO C function pow, so that it works for non-integer exponents too." -
It works very well for me. Does it show up in the block scene editor? The "Central Scene ID" option? Remote.fqa
-
This QA shows up in the block scene editor for me function QuickApp:onInit () self:debug ("Remote") local inf = api.get("/devices/"..self.id).interfaces for _,i in ipairs(inf) do if i=='zwaveCentralScene' then inf=nil; break end end if inf then inf[#inf+1]='zwaveCentralScene' self:addInterfaces(inf) end self:debug(json.encode(inf)) self: updateProperty ( "centralSceneSupport" , { {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 1 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 2 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 3 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 4 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 5 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 6 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 7 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 8 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 9 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 10 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 11 }, {keyAttributes = { "Pressed" , "Released" , "HeldDown" , "Pressed2" , "Pressed3" }, keyId = 12 }, }) end
-
Have you set interfaces = { 'zwaveCentralScene' } ?
-
function dumpScene(id) local s,c,f = api.get("/scenes/"..id) c = json.decode(s.content) f = io.open("Scene_"..id.."_actions.lua","w"); f:write(c.actions); f:close() f = io.open("Scene_"..id.."_conditions.lua","w"); f:write(c.conditions); f:close() f = io.open("Scene_"..id..".lua","w"); f:write(json.encode(s)); f:close() end --- Download scene from HC3 dumpScene(13) --- Edit Scene_13_actions.lua ... --- Edit Scene_13_conditions.lua ... function restoreScene(id) local f,a,c,s f = io.open("Scene_"..id.."_actions.lua","r"); a=f:read("*all"); f:close() f = io.open("Scene_"..id.."_conditions.lua","r"); c=f:read("*all"); f:close() f = io.open("Scene_"..id..".lua","r"); s=f:read("*all"); f:close() s = json.decode(s) s.content=json.encode({conditions=c,actions=a}) api.put("/scenes/"..id,s) end --- ... then restore scene to HC3 restoreScene(13)
-
Fair enough. I stand corrected, removeChildDevice() is called when children are deleted in the IU, so the onAction hook will work. You could also intercept calls to the method. function QuickApp:onInit() local orgRemoveChildDevice = self.removeChildDevice function self:removeChildDevice(id) self:debug("Child ",id," is about to be deleted") -- do other stuff orgRemoveChildDevice(self,id) end end
-
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
jang a répondu à un(e) sujet de Lazer dans Quick App Developpeur
Ok, I understand. Good luck :-) -
Quick App - Gestionnaire d'Événements Automatique - GEA pour HC3
jang a répondu à un(e) sujet de Lazer dans Quick App Developpeur
Is it a GEA syntax problem or api? If it's the api this is what I use in ER4 -- id to profile name function self:profileName(id) for _,p in ipairs(api.get("/profiles").profiles) do if p.id == id then return p.name end end end -- profile name to id function self:profileId(name) for _,p in ipairs(api.get("/profiles").profiles) do if p.name == name then return p.id end end end -- set active profile if id ~= nil, or return current active profile if id == nil function self:activeProfile(id) if id then if type(id)=='string' then id = self:profileName(id) end assert(id,"activeProfile(id) - no such id/name") return api.put("/profiles",{activeProfile=id}) and id end return api.get("/profiles").activeProfile end -
When a child is deleted (from Lua or UI) you get a 'DeviceRemovedEvent' in / refreshStates The QuickApp will also update the self.childDevices table. Why don't you store your extra info in the child table? self.childDevices [childID] .extraInfo = ... it's just the child instance I don't think r emoveChildDevice (...) is called by the QA if you delete the child in the UI.