Aller au contenu
TonyC

HC3 - 5.040.37 - 23/07/2020

Recommended Posts

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é par jjacques68

Partager ce message


Lien à poster
Partager sur d’autres sites

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

 

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

ç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é par jjacques68

Partager ce message


Lien à poster
Partager sur d’autres sites

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 :15:

[
  {
    "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": []
      }
    ]
  },
...
]

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Mais là ton filtre n'est pas sur l'API /devices, mais /devicenotifications, je ne pense pas que ça fonctionne

Partager ce message


Lien à poster
Partager sur d’autres sites

@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 :rolleyes:) 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

 

Partager ce message


Lien à poster
Partager sur d’autres sites

@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 1
J'ai fais quelques essais et j'arrive à la même conclusion que toi

Envoyé de mon BLA-L29 en utilisant Tapatalk

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

@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

  • Like 2

Partager ce message


Lien à poster
Partager sur d’autres sites

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...

Partager ce message


Lien à poster
Partager sur d’autres sites

@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 hc3
Je crois même qu'il n'y a plus grand monde qui fait du lua

Envoyé de mon BLA-L29 en utilisant Tapatalk

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 1 minute, mprinfo a dit :

il faudra bien expliquer que cela fonctionne aussi pour hc2

ça faudra tester...

Partager ce message


Lien à poster
Partager sur d’autres sites

Moi je peux
J'aime ma box est elle me le rend bien

Envoyé de mon BLA-L29 en utilisant Tapatalk

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites
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

Partager ce message


Lien à poster
Partager sur d’autres sites

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é ?

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

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.

Partager ce message


Lien à poster
Partager sur d’autres sites

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

Partager ce message


Lien à poster
Partager sur d’autres sites

Tu as aussi une très bonne explication dans le tuto pour le client http
Bon 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

Partager ce message


Lien à poster
Partager sur d’autres sites

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 ?

Partager ce message


Lien à poster
Partager sur d’autres sites

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é par jjacques68

Partager ce message


Lien à poster
Partager sur d’autres sites

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 :D

 

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

oulà ton exemple me donne mal au cheveu qui me reste. :) 

faut que je l'étudie avec du debug...

 

merci pour les explications !

Partager ce message


Lien à poster
Partager sur d’autres sites

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.

Partager ce message


Lien à poster
Partager sur d’autres sites

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é par jjacques68

Partager ce message


Lien à poster
Partager sur d’autres sites

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 ?

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Oui une belle conneries
La section pour les nuls est en mode lecture seule
C'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

  • Like 2

Partager ce message


Lien à poster
Partager sur d’autres sites

×