jjacques68 Posté(e) le 28 juillet 2020 Signaler Posté(e) le 28 juillet 2020 (modifié) après pour les filtres dans les api.get, j'ai déjà beaucoup galéré ! il me semble qu'on peut pas filtrer sur toutes les propriétés existantes, et surtout on peut pas cumuler si ? par exemple filtré sur une propriété qui est elle même un tableau ? on peut pas filtrer sur l'élément x de ce tableau de cette propriété ? Modifié le 28 juillet 2020 par jjacques68
Lazer Posté(e) le 28 juillet 2020 Signaler Posté(e) le 28 juillet 2020 On peut filtrer pas mal de choses, exemples en stock : /api/devices?visible=true returns devices with visible equal to 'true' /api/devices?property=[batteryLevel,100] returns devices with property batteryLevel equal to 100 /api/devices?property=[unit,%CE%BCg/m3] returns devices with unit equal to µg/m3 /api/devices?interface=light returns devices with light interface /api/devices?type=com.fibaro.netatmoWeatherStation returns Netatmo Weather Station /api/devices?baseType=com.fibaro.weather returns Weather plugins /api/devices/?property=isLight /api/devices?interface=zwave&parentId=1 1
jjacques68 Posté(e) le 28 juillet 2020 Signaler Posté(e) le 28 juillet 2020 (modifié) ça ok ! et on peut les cumuler ? ÉDIT : oui pardon j'avais pas vu le dernier ! bon j'essayerais... merci encore pour les tuyaux !! Modifié le 28 juillet 2020 par jjacques68
jjacques68 Posté(e) le 28 juillet 2020 Signaler Posté(e) le 28 juillet 2020 alors un petit exemple, je pourrais gagne un api.get(), celui qui liste tous les devices, si j'utilise l'api : /deviceNotifications/v1 mais comment filtrer les éléments qui sont active = true ?? J'ai essayé : ListeDevice = api.get("/deviceNotifications/v1?notifications=[active,true]") ListeDevice = api.get("/deviceNotifications/v1?active=true") ListeDevice = api.get("/deviceNotifications/v1?=[active,true]") Mais à chaque fois il me retourne la liste entière [ { "deviceId": 3, "notifications": [ { "active": false, "label": "labels.deviceNotifications.settings.type.Unavailable", "type": "Unavailable", "interval": { "type": "once" }, "channels": [], "users": [ 2 ] } ] }, { "deviceId": 7, "notifications": [ { "active": false, "label": "labels.deviceNotifications.settings.type.Unavailable", "type": "Unavailable", "interval": { "type": "once" }, "channels": [], "users": [] } ] }, ... ]
Lazer Posté(e) le 29 juillet 2020 Signaler Posté(e) le 29 juillet 2020 Mais là ton filtre n'est pas sur l'API /devices, mais /devicenotifications, je ne pense pas que ça fonctionne
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 @Lazer : alors j'arrive pas à trouver le moyen de mieux filtrer mes device pour ce coup là... Franchement, je pense que qqun de compétent (si tu vois ce que je veux dire ) créé un topic sur la manière de filtrer les api.get()... Visiblement, on peut pas filtrer tout ce qu'on veut. Mais on sait pas ce qu'on peut faire ou pas J'ai vu qu'il existait des moyens de comparaison (gt, lt ge, le, equal, ...) et pas moyen de les utiliser C'est galère quand il faut descendre dans l'arborescence de la table json... bref, en plus c'est pas franchement pas documenté... Ce serait vraiment top que qqun le fasse , je le ferai bien, mais je m'y connais pas assez, et rien sur le fofo officiel... je dis ça mais je dis rien sinon : je viens de modifier ce QA pour mes notifications : J'ai réussi à me passer d'une boucle (celle qui contient la liste des types d'actions dans ma variable) J'ai mis le code qui modifie l'api pour chaque device dans une fonction récursive. Et ben mon vieux, rien que ça , ça change la vie, la CPU mon franchement moins... MAIS ça continue à planter de temps à autre... ??? --[[----------------------------------------------------------------------------------------------- Active/désactive les notifications push V2 - 30/07/2020 - fonction récursive pour la modification V1 - 25/03/2020 - original -------------------------------------------------------------------------------------------------]] function QuickApp:onInit() __TAG = string.format("QA_%s_%s",self.id, self.name) self:debug("onInit") self.ListeEvent = { ["IsOpening"]=true, --Volet ouvert ["IsClosing"]=true, --Volet fermé ["TurningOn"]=true, --lumière ON ["TurningOff"]=true, --lummière OFF ["Motion"]=true, --détection PIR ["Flood"]=true, --détection inondation ["Opening"]=true, --ouverture d'une porte/fenêtre } end function QuickApp:turnOn() self:updateProperty("value", true) self:UpdateNotif(true) end function QuickApp:turnOff() self:updateProperty("value", false) self:UpdateNotif(false) end -------------------------------------------------------- -- Modifie l'API du device si son evenement est dans la liste -------------------------------------------------------- function QuickApp:ModifyNotif(id, value) --récupère les notifications de ce device MyNotif = api.get("/deviceNotifications/v1/"..id) --pour chaque notif de ce device, si trouve l'evenement, le modifie for j = 1, #MyNotif do if self.ListeEvent[MyNotif[j].type] then MyNotif[j].active = value end end --applique les modifications pour ce device api.put("/deviceNotifications/v1/"..id, MyNotif) end -------------------------------------------------------- -- Fonction Pincipale, liste tous les device visible -------------------------------------------------------- function QuickApp:UpdateNotif(value) --liste tous les device VISIBLE ListeDevice = api.get("/devices/?visible=true") --pour chaque device trouvés for i = 1, #ListeDevice do fibaro.setTimeout(0, function() self:ModifyNotif(ListeDevice[i].id, value) end) end self:trace("Notification = "..tostring(value)) end
mprinfo Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 @jjacques68 tu peux créer un topic sur le sujet et mettre ce que tu as déjà trouvéEnsuite avec les réponses tu mets à jours le poste 1J'ai fais quelques essais et j'arrive à la même conclusion que toiEnvoyé de mon BLA-L29 en utilisant Tapatalk 1
Lazer Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 @jjacques68 je n'y connais pas plus que toi non plus en /api/devices, car ce n'est pas documenté par Fibaro, donc il faut tâtonner pour trouver les filtres utilisables. Comme dit mprinfo, tu peux créer un topic regroupant les filtres qui fonctionnent qu'on complètera dans le temps 2
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 je le ferais avec plaisir, mais ce sera lite... du moins au début, en espérant que la communauté alimente le sujet... sinon je continue mon optimisation du script qui plante : j'ai remplacé : ListeDevice = api.get("/devices/?visible=true") par : ListeDevice = fibaro.getDevicesID({visible=true}) ici, j'ai absolument pas besoin de toutes les infos des device que me donne le api.get(). J'ai juste besoin de la liste des device, déjà ça soulage la RAM et je prends beaucoup moins de temps à avoir la liste des ID (et ça j'avoue avoir fait cette connerie dans beaucoup de script...) Et du coup c'est plus facile d'exploiter la table également... ça rejoint la remarque de @mprinfo qui disait d'utiliser les fonctions fibaro... ben là c'est un bon exemple... Ensuite je me suis rendu compte que je faisais un api.put() même pour des device qui n'ont pas la propriété concernée ! Ne pouvant mieux filtrer la liste des device, je vérifie donc par code la présence de cette propriété avant de continuer -> c'est con ! mais j'avais pas fait gaffe !! Bon malgré ça, ça plante toujours aléatoirement, mais très rarement... donc là je trace pour chaque fonction exécutée, le "start" et le "end" avec l'ID en cours de modifications. ça m'explose le debug, mais je verrais bien sur quelle device ça bloque, peut être que c'est toujours le même ! A suivre ! PS : @Lazer : on est bien d'accord sur le terme "récursif" d'une fonction : for blablabla do fibaro.setTimeout(0, function() MaFonction() end) end ici, "MaFonction" est récursive, c'est bien ça ? C'est comme si je lançais une multitude de "thread" ? toujours ok ? le délai à 0 me gêne, j'ai l'impression que ça "emballe" la box...
mprinfo Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 @jjacques68 te prends pas la tête tu publie ce que tu as même si c'est léger pas grave.On est pas nombreux à avoir une HC3 donc il faudra bien expliquer que cela fonctionne aussi pour hc2 et tu mets à part ce qui est pour hc3Je crois même qu'il n'y a plus grand monde qui fait du lua Envoyé de mon BLA-L29 en utilisant Tapatalk
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 il y a 1 minute, mprinfo a dit : il faudra bien expliquer que cela fonctionne aussi pour hc2 ça faudra tester...
mprinfo Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 Moi je peux J'aime ma box est elle me le rend bien Envoyé de mon BLA-L29 en utilisant Tapatalk 1
Lazer Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 il y a 17 minutes, jjacques68 a dit : ici, "MaFonction" est récursive, c'est bien ça ? C'est comme si je lançais une multitude de "thread" ? toujours ok ? Non, tu confonds 3 notions : - récursivité = une fonction qui s'appelle elle-même => parfaitement réalisable sur HC2 et HC3 - multi-thread = plusieurs instances d'un même code qui s'exécutent simultanément (très difficile à gérer dès lors les différents threads manipulent la même donnée) => impossible sur HC2 et HC3, les QuickApps sont mono-threadés. Sur HC2 les Scènes pouvaient avoir plusieurs instances simultanément, mais ce n'était pas du multi-thread pour autant, car c'était autant de process indépendants (on appelle cela un fork... Les différents processus s'exécutent indépendamment et ne partagent pas les mêmes données) - asynchronisme : le lancement d'une fonction s’exécute "plus tard", dès la fin du code en cours d'exécution (cas du settimout(0...)), ou bien plus tard (settimeout(xxx, ..)), possible sur les scènes depuis la HC2, et sur les QuickApps depuis la HC3
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 ok très bien. donc dans ce ca précis, le fait de passer par l'asynchrone suffit où il faut que je fasse une vrai récursivité ? 1
Lazer Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 non pas besoin, c'était bien l'asynchronisme qui a amélioré le fonctionnement de ton script. Car la HC3 attend des QuickApps qu'ils rendent la main régulièrement. Si un QuickApp part dans une boucle infinie (comme on le faisait avec les Main Loops des VD), alors la HC3 peut considérer la QA comme planté... Note qu'un sleep() ne rend pas la main au système, c'est bien le setTimeout() qu'il faut. Mais le setTimeout ne provoque pas une pause dans un code linéaire, il provoque l'appel d'une nouvelle fonction, il faut donc structurer son code différemment. L'utilisation des fonctions HTTPClient:request() également, ou plus exactement l'appel des fonctions success() ou error() en retour Et bien sûr, on peut combiner asynchronisme et récursivité Mais ce n'est plus de la vraie récursivité dans ce cas, car dans une algo récursif traditionnel, on attend la valeur de retour de la fonction apellée.... tandis qu'en asynchrone, on ne récupère jamais la valeur de retour de la fonction appelée, puisqu'elle s'exécute après le déroulement du code en cours Pas simple.... je ne sais pas si c'est clair.
Lazer Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 Une remarque sur la boucle infinie et le sleep() qui ne rend jamais la main. Supposons le code suivant : while true do print("Hello") sleep(60*1000) end Il ne fait donc rien 99,999999999999 du temps (approximativement :D ) et affiche une ligne chaque minute. Pourtant, comme il est synchrone et ne rend jamais la main, il empêche les autres événements sur le QuickApp. Par exemples : clic sur un bouton, mise à jour de sa valeur, etc.... Donc la HC3 va considérer qu'il est planté car il ne fonctionne pas comme attendu.... et l'utilisateur s'en rendra vite compte s'il ne se produit rien quand il tente d’interagir avec le QA
mprinfo Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 Tu as aussi une très bonne explication dans le tuto pour le client httpBon je viens de lire ça fait mal la tête comme on dit chez nous Je vois boire une bonne bière pour faire passer tout cela Envoyé de mon BLA-L29 en utilisant Tapatalk
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 ah mais attend ! suis bête ! j'utilise souvent la récursivité ! quand par exemple on veut bouclé une fonction à intervalle régulier pour contrôler une heure et déclencher des actions ! function MaFonction() ... fibaro.setTimeout(60*1000, function() MaFonction() end) end c'est bien ça ?
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 (modifié) en attendant, j'ai trouvé comment rendre le plantage du QA, donc de la box, non plus aléatoire, mais bien répétable à souhait ! il me suffit d'exécuter le QA (donc 3 à 4 secondes pour tout traiter) et de déclencher un device (capteur, ou actionneur) pendant ce temps là. Et ça loupe pas, crash instantané ! alors : hypothèse : à chaque changement d'état d'un device, la box fait un appel à l'api /deviceNotifications/ pour savoir si elle doit envoyer une notification ou non. Et moi pendant ce temps là je suis entrain de modifier cette API. Donc ça aime pas et plante tout. Pourtant... avant la mise à jour c'était ok, jamais planté, et je confirme que ce scénario arrivait souvent... Mais alors si c'est bien ça, je sais absolument pas comment le contourner ! Modifié le 30 juillet 2020 par jjacques68
Lazer Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 Ah oui elle ne doit pas aimer Changement de firmware, changement de mode de fonctionnement interne, et avec un code borderline, c'est le crash assuré !! il y a 15 minutes, jjacques68 a dit : quand par exemple on veut bouclé une fonction à intervalle régulier pour contrôler une heure et déclencher des actions ! oui... mais non pas vraimeent car comme dit dans un post précédent, à partir du moment où tu es asynchrone, ce n'est plus vraiment de la récursivité, car tu ne récupères jamais le code de retour de la fonction quand ta nouvelle fonction MaFonction() s'exécute, la précédente est en réalité déjà terminée depuis longtemps. Un vrai algo récursif, ce n'est pas ça. La fonction peut s’appeler elle-même plusieurs fois de façon imbriquée on utilise souvent pour traiter des données, et les découper par tranche, une sorte de dichotomie de plus en plus fine Tu as un vrai code récursif ici, avec la fonction browse() : Note que ça peut être dangereux un code récursif, car tu peux partir dans une boucle d'appel infini de fonction, et ne jamais en sortir. Ça fini toujours en crash (saturation mémoire) Tu as vu Inception ? Bah c'est exactement ça 1
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 oulà ton exemple me donne mal au cheveu qui me reste. faut que je l'étudie avec du debug... merci pour les explications !
Lazer Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 Mon exemple parcoure un tableau. Pour chaque élément de ce tableau, si on trouve un sous-élement qui est lui-même de type tableau, alors on appelle à nouveau la fonction pour parcourir l'intérieur. Et ainsi de suite. Là tu as la récursivité. Si par exemple le tableau contient 10 sous-tableaux imbriqués, alors on aura jusqu'à 10 appels récursifs enchainés. Je suis sûr que sur Internet tu trouveras plein d'exemples pratique de récursivité. Cela dit on a dévié de la discussion initiale, la récursivité ne répond pas vraiment à ta problématique.
jjacques68 Posté(e) le 30 juillet 2020 Signaler Posté(e) le 30 juillet 2020 (modifié) non mais c'est super interessant. pour mon problème initiale de plantage... je réfléchirais en dormant là je sèche. Suis pas du genre à lâcher l'affaire, mais là... à moins d'attendre la prochaine MAJ, en espérant... sinon à l'ancienne, je désactive toutes les notifications des device, et je les gère depuis une scène ! Ah mais non, y a pas de multi instance des scènes ! donc faudra que j'utilise mon QA qui interroge le refreshState, qui tourne très bien... lui... Mais ça veut dire : gérer une liste de device, gérer la valeur du device, bla-bla-bla ... super lourd ! EDIT : peut être essayer de protéger l'appel de la foncation par un pcall... Modifié le 30 juillet 2020 par jjacques68
jjacques68 Posté(e) le 31 juillet 2020 Signaler Posté(e) le 31 juillet 2020 Viens de faire une première grosse passe sur mes scripts... Et bien j'en ai modifié pas mal de code, question optimisation... J'ai bien l'impression, d'après la charge CPU, que ça a fait du bien... y a comme on dirait, plus d'oxygène Et je peux encore faire mieux, mais faut remettre en question l'algo de base pur certain... j'ai déjà des idées @Lazer j'ai commencé un topic pour le filtrage des device, je l'ai mis dans la section "pour les nuls", mais visiblement il faut qu'un admin approuve le sujet, j'ai fais une connerie ? 1
mprinfo Posté(e) le 31 juillet 2020 Signaler Posté(e) le 31 juillet 2020 Oui une belle conneries La section pour les nuls est en mode lecture seuleC'est un admin qui déplace le topic dans cette section après on ne peut modifier sans passer par un administrateur Envoyé avec Tapatalk 2
Messages recommandés