Ceci n'est pas un tuto, mais plutôt un topic de travail sur l'avancement de mes tests dans l'utilisation de l'API refreshStates, son optimisation, son impact sur les performances de la box, ses limites, etc.   Pour rappel, refreshStates permet de récupérer en temps réel tous les événements sur la box. A l'origine, elle a été créée par Fibaro pour les mises à jours de l'interface Web et des applications mobiles. Mais on peut tout à fait l'utiliser dans nos codes LUA, au sein même des QuickApps, puisque ceux-ci ne disposant pas de déclencheurs (triggers) comme les Scènes, cela leur permet ainsi de simuler ces fameux triggers.   Actuellement, j'ai un seul QuickApp (GEA) qui utilise cette API, je vais commencer par créer plusieurs QA qui utilisent cette même API et voir comment réagit la box. Le risque probable, c'est une occupation CPU supérieure, pouvant entrainer des ralentissement, voire plantages.   Voici un premier bout de code, optimisé "à fond", c'est à dire que pour optimiser au maximum les performances du LUA, je n'utilise que des variables locales, l'objectif étant de limiter autant que possible l'usage des variables (et fonctions) globales, ainsi que le parcours des tables (l'appel d'une variable globale revient à parcourir la table _G), opérations très consommatrices de cycles CPU.   De même, le parcours de la table se fait avec for, plus rapide que ipairs(), lui même plus rapide que pairs() Le calcul du nombre d'éléments de la table se fait avant d'entrer dans la boucle for, afin de ne pas refaire le calcul à chaque passage dans la boucle for.   Toutes ces optimisations LUA rendent le code moins lisible, donc je les réserve uniquement à cette boucle infinie loop(), car elle va se répéter un grand nombre de fois, à très haute fréquence. Quelques nanosecondes à chaque cycle, ça fini par faire mal mal de secondes à la fin. Le reste du code du QuickApp (non représenté ici) sera développé de façon plus traditionnelle.   Pour ces tests, je commence avec un intervalle de 250 ms, soit 1/4 de seconde, ce qui me parait quasiment instantané à l'échelle humaine, et bien suffisant pour mettre à jour l'état d'un QuickApp dans nos scénarios domotiques. Sur GEA, je tourne actuellement à 100ms et ça ne pose à priori aucun problème, je sais que d'autres personnes sur le forum sont descendues à 50 ms. Mais je suppose que d'avoir plusieurs QA avec un intervalle de 50ms ça sera beaucoup plus stressant que 250ms, d'où mon choix de commencer mes tests avec 250 ms.
En revanche, en cas d'erreur sur la requête HTTP, j'ai mis un timeout à 5000 ms, soit 5 secondes. Je me dit que si la requête a échoué, c'est peut être parce que la box est saturée, donc attendre plusieurs secondes ne peut que faire du bien.   Évidemment j'utilise pcall() à chaque appel de fonction risquée, afin de protéger le code contre tout plantage, et tant pis pour le (léger) risque d'impact sur les performances.   Je vais lancer ce bout de code sur plusieurs QA pendant plusieurs heures, et étudier comment se comporte la box (graph CPU)   __TAG = "QA_REFRESHSTATES_" .. plugin.mainDeviceId function QuickApp:onInit() self:trace("") self:trace("onInit") self:trace("") end function QuickApp:buttonLoop(event) local lastRefresh = 0 local http = net.HTTPClient() local http_request = http.request local json_decode = json.decode local pcall = pcall local type = type local setTimeout = setTimeout local self_debug = self.debug -- Boucle d'attente d'événements instantanés local function loop() local status, err = pcall(function() local stat, res = http_request(http, "http://127.0.0.1:11111/api/refreshStates?last=" .. lastRefresh, { success = function(res) local status, states = pcall(function() return json_decode(res.data) end) if status then lastRefresh = states.last or 0 local events = states.events local nbEvents = #(events or {}) if nbEvents > 0 then self_debug(self, nbEvents) end for i = 1, nbEvents do local event = events[i] local id = event.data and event.data.id --if id == 123 then --self:debug("Event :", json.encode(event)) --end end else self:error(states or "json.decode() failed") end setTimeout(loop, 250) end, error = function(res) self:error("Error : API refreshStates :", res) setTimeout(loop, 5000) end, }) end) if not status then self:error(err) setTimeout(loop, 5000) end end loop() end PS : pour ce test il faut créer un bouton buttonLoop pour lancer la boucle.