Aller au contenu

jang

Membres confirmés
  • Compteur de contenus

    215
  • Inscription

  • Dernière visite

  • Jours gagnés

    45

Tout ce qui a été posté par jang

  1. jang

    Command Class Time Parameters

    ...it's kind of an mqtt mechanism between QAs... but with a much simpler api...
  2. jang

    Command Class Time Parameters

    Oh, finally someone discovered that function :-) Yes, it's really cool and quite efficient as the publisher only sends to subscribers actually subscribing on the event (source filtering). Also it works well with the fibaroExtra event mechanism that makes it easy to work with HC3 device and internal events.
  3. I wouldn't call it a mega optimization... If it would run million of times / sec I would agree... but not for 4 times per second... Of course it's not the monthly energy savings that are of importance here but to make sure we can complete the 4 calls per seconds and still do all other stuff... ...then 0.26 microseconds is more like a micro optimization... local n,t0=100000 a = { b = function() end } c = function() end local d = function() end print("----------") t0 = os.clock() for i=1,n do a.b() end local v0 = (os.clock()-t0)*1000 print(string.format("Time '%s' = %0.6f",'a',v0/n)) t0 = os.clock() for i=1,n do c() end local v1 = (os.clock()-t0)*1000 print(string.format("Time '%s' = %0.6f",'c',v1/n)) t0 = os.clock() for i=1,n do d() end local v2 = (os.clock()-t0)*1000 print(string.format("Time '%s' = %0.6f",'d',v2/n)) local save = (v0-v2)/n printf("Saving %0.6f milliseconds per call, using local fun vs global table fun",save) printf("Saving %0.3f seconds per month, using 4 calls / second",30*24*3600*4*save/1000) ...and the answer is [19.04.2023] [07:27:56] [DEBUG] [QUICKAPP1090]: Saving 0.000264 milliseconds per call, using local fun vs global table fun [19.04.2023] [07:27:56] [DEBUG] [QUICKAPP1090]: Saving 2.734 seconds per month, using 4 calls / second
  4. Excessive typing can affect your health
  5. print(os.date("%FT%T%z"):sub(1,-3)..":00") print(os.date("%FT%T%z",os.time()+24*3600):sub(1,-3)..":00") Assuming timezone offset always even hours.
  6. jang

    CURL Token en LUA

    You shouldn't encode response.data. It's already encoded. Just use decode. The '\n' is no problem. print("My_Json:" , response.data) local My_Json = json.decode ( response.data ) access_token = My_Json.access_token token_type = My_Json.token_type expires_in = My_Json.expires_in print ( "access_token:" , access_token ) print ( "token_type:" , token_type ) print ( "expires in:" , expires_in )
  7. It's just to cater for a variable number of arguments in the provided table. Now it's just a table with an single url so it is kind of an overkill (and then we tuck on the success and error handlers at the end). By allowing join to take a function with unknown number of arguments we keep it generic and let the sendRequest deal with the number of args. Yes you need the count the number of calls and use that later to count down... because register is a key/value table you can't just use #register... I'm not sure how your 'registerscan' is implemented but I assume that the callback is called at success. Then I would add another callback for errors and implement it something like this local function scallAll(register) local n,finish=0 for _, register in pairs(register) do n=n+1 local cb = register.callback registerscan(registerNumber, function(res) cb(res) isFinished() end, -- success callback function(err) print("Err:",err) isFinished() end -- error callback ) end function isFinished() n=n-1 if n==0 then self:debug("Scan completed") end end end Yes, it's just a reuse of the name 'err'. The second err in "function(err) ..." shadows the previous definition. What's bother me now is that the code is buggy as the call to the builtin error function can't take two string error messages. The correct code would have been error(url..err)
  8. Your debug at the end is a callback when all are done. see https://forum.fibaro.com/topic/42993-wait-until-httprequest-returns/?do=findComment&comment=181106
  9. jang

    string.gsub()

    '.' is a pattern that matches any character. To match against decimal point you need to escape it with a %, use '%.'. But if you just want to replace '.' with ',' and convert to a string just use if type(DeviceProperty) == "number" then DeviceProperty = tostring(DeviceProperty):gsub("%.",",") if debugD then self:trace("Device property = "..DeviceProperty) end end If you want it with a specific number of decimals do -- 2 decimals DeviceProperty = string.format("%.02f",1.0*DeviceProperty):gsub("%.",",")
  10. jang

    Les Childs pour les Nuls

    Well, of course there was a small problem with my code.... Try this version The load and creation of children is protected with a pcall. do local childID = 'ChildID' local classID = 'ClassName' local defChildren local children = {} local undefinedChildren = {} local createChild = QuickApp.createChildDevice class 'QwikAppChild'(QuickAppChild) function QwikAppChild:__init(device) QuickAppChild.__init(self, device) self:debug("Instantiating object ",device.name) local uid = self:getVariable(childID) or "" if defChildren[uid] then children[uid]=self -- Keep table with all children indexed by uid. uid is unique. else -- If uid not in our children table, we will remove this child undefinedChildren[#undefinedChildren+1]=self.id end end function QuickApp:createChildDevice(uid,props,interfaces,className) __assert_type(uid,'string') __assert_type(className,'string') props.initialProperties = props.initialProperties or {} local qas = {{name=childID,value=uid},{name=classID,value=className}} props.initialProperties.quickAppVariables = qas props.initialInterfaces = interfaces self:debug("Creating device ",props.name) return createChild(self,props,_G[className]) end local function getVar(child,varName) for _,v in ipairs(child.properties.quickAppVariables or {}) do if v.name==varName then return v.value end end return "" end function QuickApp:loadExistingChildren(chs) __assert_type(chs,'table') local stat,err = pcall(function() defChildren = chs self.children = children function self.initChildDevices() end local cdevs,n = api.get("/devices?parentId="..self.id) or {},0 -- Pick up all my children for _,child in ipairs(cdevs) do local uid = getVar(child,childID) local className = getVar(child,classID) local childObject = _G[className] and _G[className](child) or QuickAppChild(child) self.childDevices[child.id]=childObject childObject.parent = self end end) if not stat then self:error("loadExistingChildren:"..err) end end function QuickApp:createMissingChildren() local stat,err = pcall(function() for uid,data in pairs(defChildren) do if not self.children[uid] then local props = { name = data.name, type = data.type, } self:createChildDevice(uid,props,data.interfaces,data.className) end end end) if not stat then self:error("createMissingChildren:"..err) end end function QuickApp:removeUndefinedChildren() for _,deviceId in ipairs(undefinedChildren) do -- Remove children not in children table self:removeChildDevice(deviceId) end end end ------------------------------- -- 1 - Definition of class ------------------------------- class 'Class_Temp'(QwikAppChild) -- Class NOM_Temps pour "com.fibaro.temperatureSensor" ------------------------------- -- 2 - Class constructor ------------------------------- function Class_Temp:__init(device) QwikAppChild.__init(self, device) end -------------------------------- -- 3 - Definition of children -------------------------------- local myChildren = { -- Unique ID (uid) -> child initialization data, in our case the name ["Child_Temps1"] = { name="Température1", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps2"] = { name="Température2", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps3"] = { name="Température3", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps4"] = { name="Température4", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps5"] = { name="Température5", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps6"] = { name="Température6", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, } -------------------------------- -- 4 - Initialization of children -------------------------------- function QuickApp:onInit() self:loadExistingChildren(myChildren) self:createMissingChildren() self:removeUndefinedChildren() self:update_child("Child_Temps5") -- example, update child with uid 'Child_Temps5' -- for uid,_ in pairs(self.children) do -- update all children -- self:update_child(uid) -- end end -------------------------------- -- 5 - Accessing children -------------------------------- function QuickApp:update_child(uid) local default_temp = 37 --- pour l'ex du tuto local default_log = " I'm bad " --- pour l'ex du tuto self.children[uid]:updateProperty("value", default_temp) self.children[uid]:updateProperty("log", default_log) end
  11. jang

    Les Childs pour les Nuls

    So, if we refine the code and create a library of it do local childID = 'ChildID' local classID = 'ClassName' local defChildren children = {} local undefinedChildren = {} local createChild = QuickApp.createChildDevice class 'QwikAppChild'(QuickAppChild) function QwikAppChild:__init(device) QuickAppChild.__init(self, device) local uid = self:getVariable(childID) or "" if defChildren[uid] then children[uid]=self -- Keep table with all children indexed by uid. uid is unique. else -- If uid not in our children table, we will remove this child undefinedChildren[#undefinedChildren+1]=self.id end end function QuickApp:createChildDevice(uid,props,interfaces,className) __assert_type(uid,'string') __assert_type(className,'string') props.initialProperties = props.initialProperties or {} local qas = {{name=childID,value=uid},{name=classID,value=className}} props.initialProperties.quickAppVariables = qas props.initialInterfaces = interfaces return createChild(self,props,_G[className]) end local function getVar(child,varName) for _,v in ipairs(child.properties.quickAppVariables or {}) do if v.name==varName then return v.value end end return "" end function QuickApp:loadExistingChildren(chs) __assert_type(chs,'table') defChildren = chs self.children = children function self.initChildDevices() end local cdevs,n = api.get("/devices?parentId="..self.id) or {},0 -- Pick up all my children for _,child in ipairs(cdevs) do local uid = getVar(child,childID) local className = getVar(child,classID) local childObject = _G[className] and _G[className](child) or QuickAppChild(child) self.childDevices[child.id]=childObject childObject.parent = self end end function QuickApp:createMissingChildren() for uid,data in pairs(defChildren) do if not self.children[uid] then local props = { name = data.name, type = data.type, } self:createChildDevice(uid,props,data.interfaces,data.className) end end end function QuickApp:removeUndefinedChildren() for _,deviceId in ipairs(undefinedChildren) do -- Remove children not in children table self:removeChildDevice(deviceId) end end end do local childID = 'ChildID' local classID = 'ClassName' local defChildren children = {} local undefinedChildren = {} local createChild = QuickApp.createChildDevice class 'QwikAppChild'(QuickAppChild) function QwikAppChild:__init(device) QuickAppChild.__init(self, device) local uid = self:getVariable(childID) or "" if defChildren[uid] then children[uid]=self -- Keep table with all children indexed by uid. uid is unique. else -- If uid not in our children table, we will remove this child undefinedChildren[#undefinedChildren+1]=self.id end end function QuickApp:createChildDevice(uid,props,interfaces,className) __assert_type(uid,'string') __assert_type(className,'string') props.initialProperties = props.initialProperties or {} local qas = {{name=childID,value=uid},{name=clsID,value=className}} props.initialProperties.quickAppVariables = qas props.initialInterfaces = interfaces return createChild(self,props,_G[className]) end local function getVar(child,varName) for _,v in ipairs(child.properties.quickAppVariables or {}) do if v.name==varName then return v.value end end return "" end function QuickApp:loadExistingChildren(chs) __assert_type(chs,'table') defChildren = chs self.children = children function self.initChildDevices() end local cdevs,n = api.get("/devices?parentId="..self.id) or {},0 -- Pick up all my children for _,child in ipairs(cdevs) do local uid = getVar(child,childID) local className = getVar(child,classID) local childObject = _G[className] and _G[className](child) or QuickAppChild(child) self.childDevices[child.id]=childObject childObject.parent = self end end function QuickApp:createMissingChildren() for uid,data in pairs(defChildren) do if not self.children[uid] then local props = { name = data.name, type = data.type, } self:createChildDevice(uid,props,data.interfaces,data.className) end end end function QuickApp:removeUndefinedChildren() for _,deviceId in ipairs(undefinedChildren) do -- Remove children not in children table self:removeChildDevice(deviceId) end end end then we can use it like this ------------------------------- -- 1 - Definition of class ------------------------------- class 'Class_Temp'(QwikAppChild) -- Class NOM_Temps pour "com.fibaro.temperatureSensor" ------------------------------- -- 2 - Class constructor ------------------------------- function Class_Temp:__init(device) QwikAppChild.__init(self, device) end -------------------------------- -- 3 - Definition of children -------------------------------- local myChildren = { -- Unique ID (uid) -> child initialization data, in our case the name ["Child_Temps1"] = { name="Température1", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps2"] = { name="Température2", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps3"] = { name="Température3", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps4"] = { name="Température4", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps5"] = { name="Température5", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, ["Child_Temps6"] = { name="Température6", type="com.fibaro.temperatureSensor", className='Class_Temp', interfaces = {'battery'}, }, } -------------------------------- -- 4 - Initialization of children -------------------------------- function QuickApp:onInit() self:loadExistingChildren(myChildren) self:createMissingChildren() self:removeUndefinedChildren() self:update_child("Child_Temps5") -- example, update child with uid 'Child_Temps5' -- for uid,_ in pairs(self.children) do -- update all children -- self:update_child(uid) -- end end -------------------------------- -- 5 - Accessing children -------------------------------- function QuickApp:update_child(uid) local default_temp = 37 --- pour l'ex du tuto local default_log = " I'm bad " --- pour l'ex du tuto self.children[uid]:updateProperty("value", default_temp) self.children[uid]:updateProperty("log", default_log) end
  12. jang

    Les Childs pour les Nuls

    ...but you needed to reboot your HC3
  13. jang

    Les Childs pour les Nuls

    I think this became a good example, I will repost the code in the (main) Fibaro forum with credits to you. https://forum.fibaro.com/topic/49113-hc3-quickapps-coding-tips-and-tricks/?do=findComment&comment=260188
  14. jang

    Les Childs pour les Nuls

    This version will remove children that are not in the children table. It can be useful if you change the number of children (reduce them), or the code creates children infinitely like the last version... ;-) local childrenToDelete,children = {} local childID = 'Nappe_Child_ID' ------------------------------- -- 1 - Création d'un Child ------------------------------- -- Child Température : function QuickApp:createChildTmps(ID,Nom) local child = self:createChildDevice({ name = Nom, type = "com.fibaro.temperatureSensor", initialProperties = {quickAppVariables = {{name=childID,value=ID}}}, }, NOM_Temps) end ------------------------------- -- 2 - Définition des classes ------------------------------- class 'NOM_Temps'(QuickAppChild) -- Class NOM_Temps pour "com.fibaro.temperatureSensor" ------------------------------- -- 3 - Constructeur ------------------------------- -- Constructeur __init pour la classe NOM_Temps function NOM_Temps:__init(device) QuickAppChild.__init(self, device) local uid = self:getVariable(childID) or "" if children[uid] then children[uid]=self -- Keep table with all children indexed by name. Assumes name unique. else childrenToDelete[#childrenToDelete+1]=self.id -- child to remove end end -------------------------------- -- 4 - Initialisation des Childs -------------------------------- children = { -- Unique ID -> Name ["Child_Temps1"] = "Température1", ["Child_Temps2"] = "Température2", ["Child_Temps3"] = "Température3", ["Child_Temps4"] = "Température4", ["Child_Temps5"] = "Température5", ["Child_Temps6"] = "Température6", } function QuickApp:onInit() self:initChildDevices({ ["com.fibaro.temperatureSensor"] = NOM_Temps -- Température }) for uid,Nom in pairs(children) do if type(Nom)=='string' then -- Uninitialized child self:createChildTmps(uid,Nom) -- ...create child end end for _,deviceId in ipairs(childrenToDelete) do self:removeChildDevice(deviceId) end self:Mise_a_jour_des_Childs("Child_Temps5") end function QuickApp:Mise_a_jour_des_Childs(Nom) local variable_qui_donne_la_temperature = 37 --- pour l'ex du tuto local variable_pour_le_log = " I'm bad " --- pour l'ex du tuto children[Nom]:updateProperty("value", variable_qui_donne_la_temperature) children[Nom]:updateProperty("log", variable_pour_le_log) end
  15. jang

    Les Childs pour les Nuls

    So, there was another bug in creating the childDevice. The initialProperties should be quickAppVariables = ... If you copy the last post in full it should work.
  16. jang

    Les Childs pour les Nuls

    You could also add code to automatically delete children that you don't use/need (e.g. children not in the children table)
  17. jang

    Les Childs pour les Nuls

    I made a change in the original code if type ( Name )== 'string' instead of the wrong code type(children[Name])=='string' Did you change that? Otherwise you will create the children every time you restart.
  18. jang

    Les Childs pour les Nuls

    No problem, just fixed it myself.
  19. jang

    Les Childs pour les Nuls

    The problem with using the name as the unique key is that you may want the children to have the same name - or the user can change the name in the Web UI of your child... So, instead you can store the unique id in a quickAppVariable, similar to in your own example, and then create a table mapping these unique ids to the child objects. It becomes a little bit more complex. local children local childID = 'Nappe_Child_ID' ------------------------------- -- 1 - Création d'un Child ------------------------------- -- Child Température : function QuickApp:createChildTmps(ID,Nom) local child = self:createChildDevice({ name = Nom, type = "com.fibaro.temperatureSensor", initialProperties = { quickAppVariables = {{name=childID,value=ID}}}, }, NOM_Temps) end ------------------------------- -- 2 - Définition des classes ------------------------------- class 'NOM_Temps'(QuickAppChild) -- Class NOM_Temps pour "com.fibaro.temperatureSensor" ------------------------------- -- 3 - Constructeur ------------------------------- -- Constructeur __init pour la classe NOM_Temps function NOM_Temps:__init(device) QuickAppChild.__init(self, device) children[self:getVariable(childID)]=self -- Keep table with all children indexed by name. Assumes name unique. end -------------------------------- -- 4 - Initialisation des Childs -------------------------------- children = { -- Unique ID -> Name ["Child_Temps1"] = "Température1", ["Child_Temps2"] = "Température2", ["Child_Temps3"] = "Température3", ["Child_Temps4"] = "Température4", ["Child_Temps5"] = "Température5", ["Child_Temps6"] = "Température6", } function QuickApp:onInit() self:initChildDevices({ ["com.fibaro.temperatureSensor"] = NOM_Temps -- Température }) for uid,Nom in pairs(children) do if type(Nom)=='string' then -- Uninitialized child self:createChildTmps(uid,Nom) -- ...create child end end self:Mise_a_jour_des_Childs("Child_Temps5") end function QuickApp:Mise_a_jour_des_Childs(Nom) local variable_qui_donne_la_temperature = 37 --- pour l'ex du tuto local variable_pour_le_log = " I'm bad " --- pour l'ex du tuto children[Nom]:updateProperty("value", variable_qui_donne_la_temperature) children[Nom]:updateProperty("log", variable_pour_le_log) end .
  20. jang

    Les Childs pour les Nuls

    It should not work. children={} is a table you define where you keep a map <name> -> <child>. The "builtin" table, self.childDevices keep a map <deviceID> -> <child>, which is not as useful when working with the children. However, deviceID is always unique so that is the reason why they have that mapping. If we know that the names are unique it is more helpful to have a name to child mapping, like in the example. Otherwise we can also give our children a unique id that we store in a quickAppVariable, like in your example, and index on that.
  21. jang

    Les Childs pour les Nuls

    If you have 6 predefined children with unique names local children ------------------------------- -- 1 - Création d'un Child ------------------------------- -- Child Température : function QuickApp:createChildTmps(Nom) local child = self:createChildDevice({name = Nom, type = "com.fibaro.temperatureSensor",}, NOM_Temps) end ------------------------------- -- 2 - Définition des classes ------------------------------- class 'NOM_Temps'(QuickAppChild) -- Class NOM_Temps pour "com.fibaro.temperatureSensor" ------------------------------- -- 3 - Constructeur ------------------------------- -- Constructeur __init pour la classe NOM_Temps function NOM_Temps:__init(device) QuickAppChild.__init(self, device) children[self.name]=self -- Keep table with all children indexed by name. Assumes name unique. end -------------------------------- -- 4 - Initialisation des Childs -------------------------------- children = { ["Température1"] = false, ["Température2"] = false, ["Température3"] = false, ["Température4"] = false, ["Température5"] = false, ["Température6"] = false, } function QuickApp:onInit() self:initChildDevices({ ["com.fibaro.temperatureSensor"] = NOM_Temps -- Température }) for Nom,c in pairs(children) do if c==false then self:createChildTmps(Nom) end end self:Mise_a_jour_des_Childs("Température5") end function QuickApp:Mise_a_jour_des_Childs(Nom) local variable_qui_donne_la_temperature = 37 --- pour l'ex du tuto local variable_pour_le_log = " I'm bad " --- pour l'ex du tuto children[Nom]:updateProperty("value", variable_qui_donne_la_temperature) children[Nom]:updateProperty("log", variable_pour_le_log) end
  22. jang

    Les Childs pour les Nuls

    Sorry, local children = {} in the beginning of the code didn't come along when I copied the code. I fixed it in the previous post.
  23. jang

    Les Childs pour les Nuls

    Could also simplify like this. This assumes that child name is unique. You can index on some quickAppVariable too. local children = {} ------------------------------- -- 1 - Création d'un Child ------------------------------- -- Child Température : function QuickApp:createChildTmps(Nom) local child = self:createChildDevice({name = Nom, type = "com.fibaro.temperatureSensor",}, NOM_Temps) end ------------------------------- -- 2 - Définition des classes ------------------------------- class 'NOM_Temps'(QuickAppChild) -- Class NOM_Temps pour "com.fibaro.temperatureSensor" ------------------------------- -- 3 - Constructeur ------------------------------- -- Constructeur __init pour la classe NOM_Temps function NOM_Temps:__init(device) QuickAppChild.__init(self, device) children[self.name]=self -- Keep table with all children indexed by name. Assumes name unique. end -------------------------------- -- 4 - Initialisation des Childs -------------------------------- local Nom = "Température" function QuickApp:onInit() self:initChildDevices({ ["com.fibaro.temperatureSensor"] = NOM_Temps -- Température }) if not children[Nom] then self:createChildTmps(Nom) end self:Mise_a_jour_des_Childs() end function QuickApp:Mise_a_jour_des_Childs() local variable_qui_donne_la_temperature = 37 --- pour l'ex du tuto local variable_pour_le_log = " I'm bad " --- pour l'ex du tuto children[Nom]:updateProperty("value", variable_qui_donne_la_temperature) children[Nom]:updateProperty("log", variable_pour_le_log) end
  24. jang

    Fonction call

    api.get("/alarms/v1/partitions/"..partitionId).devices
  25. jang

    variable global ou self.xxx ?

    Not sure this helps, but.... local myTable = {} myTable.x = 5 function myTable:test1(x) print(self.x+x) end Defining a function with ':' is the same as defining function myTable.test1(self,x) print(self.x+x) end It inserts a variable 'self' as the first argument (Lua choses the name 'self') The above function definition is the same as myTable.test1 = function(self,x) print(self.x+x) end So the resulting myTable is now { x = 5, test1 = function(self,v) print(self.x+x) end } If we call myTable:test1(5) it is transformed to the call myTable.test1(myTable,5), taking the table on the left of ':' and passing it on as the first argument 'self' to the test1 function myTable.test1(myTable,5) and we get >10 If we define our function with '.' we can call 'self' something else... function myTable.test2(y,x) print(y.x*x) end myTable:test2(5) >25 So, 'self' is just a Lua table (object) that is sent around as the first argument to all methods, and representing the object the methods belongs to. In the common case it's the QuickApp object, but for QuickAppChild classes, it's the child object. We can define our QuickApp functions with '.' instead of ':' but we need to add the first parameter, the 'self' We can also call our QuickApp functions with '.' instead of ':' but we need to add the first argument, the 'self', explicitly. In the below case we call it 'myApp' instead of 'self' function QuickApp.test3(myApp,x) myApp.debug(myApp,myApp.x+x) end function QuickApp.onInit(myApp) myApp.x = 9 QuickApp.test3(myApp,8) end
×
×
  • Créer...