971jmd Posté(e) le 6 septembre 2018 Signaler Posté(e) le 6 septembre 2018 Salut a tous je souhaite savoir si sous 4.510 pourquoi le code suivant ne fonctionne plus http = net.HTTPClient() http:request("CODE_HTTP", {options = { method = 'GET' }, success = function(response) fibaro:debug("OK") end, error = function(err) fibaro:debug("Error: " ..err) end })
pepite Posté(e) le 7 septembre 2018 Signaler Posté(e) le 7 septembre 2018 Bonjour, Manque un peu d'infos non ? Rassure moi, ce n'est pas ton code tel quel ? Sinon avec "CODE_HTTP" comme cela ca a déjà fonctionné ;-) C'est ton code dans quel but ? Je viens d'aller voir, suis en 4.510, par exemple le WATCHDOG de @Lazer fait du net.HTTPClient) et pas de soucis.
971jmd Posté(e) le 7 septembre 2018 Auteur Signaler Posté(e) le 7 septembre 2018 salut Pepite oui effectivement j'ai pas précisé l'adresse suivante mes a jours une base SQL :http://127.0.0.1:8080/fibaro/index3.php?nomdevice=lampe ça fonctionne tres bien mai avec fibaro non: local http = net.HTTPClient() http:request("http://127.0.0.1:8080/fibaro/index3.php?nomdevice=lampe", {options = { method = 'GET' }, success = function(response) fibaro:debug("OK") end, error = function(err) fibaro:debug("Error: " ..err) end }) [DEBUG] 08:17:48: Error: Connection refused [DEBUG] 08:22:01: Error: Connection refused pour info j'utilise WAMPSERVEUR je pense que c le 127.0.0.1 que ne gère pas fibaro
pepite Posté(e) le 7 septembre 2018 Signaler Posté(e) le 7 septembre 2018 Il y a 2 heures, 971jmd a dit : http://127.0.0.1:8080 je vias certainement dire ne grosse c..mais pour moi en l'ecrivant comme ceci tu lui demande d'aller sur son propre loopback. Si sur WAMPserver, ton PC a bien une addresse IP non. Essaie avec http://IPLANDUPC:8080/....
971jmd Posté(e) le 7 septembre 2018 Auteur Signaler Posté(e) le 7 septembre 2018 j'ai tester avec : local http = net.HTTPClient() http:request("192.168.0.44:8081/fibaro/index3.php?nomdevice=coco", {options = { . . [DEBUG] 11:25:09: OK mai rien ne bouge dans ma base SQL j'ai tester depuis mon iphone en local l'adresse : 192.168.0.44:8081/fibaro/index3.php?nomdevice=coco et rien
971jmd Posté(e) le 7 septembre 2018 Auteur Signaler Posté(e) le 7 septembre 2018 j'ai trouver le problème, le WAP n'étais pas ouvert au réseaux local j'ai modifier le fichier, httpd.conf de WAP... Order Deny,Allow Allow from all Allow from 127.0.0.1 Allow from 192.168.0.44 Allow from ::1 Allow from localhost </Directory>
pepite Posté(e) le 7 septembre 2018 Signaler Posté(e) le 7 septembre 2018 Voila, parfait ;-) Well done ;-)
MAM78 Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 (modifié) Hello, Je cherche à écrire une fonction générique pour executer une requête HTTPClient. Voici mon code et j'ai quelques questions sur celui-ci : 1) Dans que cas il est conseillé d'encadrer la fonction http.request par une fonction pcall() comme ceci ? local ok = pcall(function() http:request(Query, { 2) Dans que cas il est conseillé d'encadrer la fonction json.decode, response.data par une fonction pcall() comme ceci ? pcall(json.decode, response.data) 3) Dans mon code ci-dessous le traitement des données retournée par la requête est lancé à l'intérieur de la fonction. Est-ce possible (souhaitable) que le traitement des données soit fait à l'extérieur de la requête, soit par exemple : success, data = GetData(Query) if success then traitement_data(data) end Sachant que dans le code ci-dessous, après la ligne if (status and data) then, il aurait : return true, data et dans les autres cas return false 4) Comment intercepté que la requête est tombée timeout ? Ou fait-il mettre un test pour détecter le timeout et comment faire ce test. Merci d'avance pour vos explications local TimeOut = 3000 function GetData(Query) local Synology = net.HTTPClient({ timeout = TimeOut }) local ok = function() http:request(Query, { options = { method = 'GET', headers ={ ["Content-Type"] = "application/json", ["Authorization"] = "BASIC "..User_code_API_Encode64}, data = body }, success = function(response) if response.status == 200 then Trace("blue","Traitement ok : ".."") local status, data = json.decode, response.data if (status and data) then Trace("orange"," OK -> Traitement des données") else Trace("orange"," Attention : Aucunes données à traiter") end else if response.status == 500 or response.status == 503 then Trace("orange","Erreur d'indisponibilité du serveur") else Trace("orange","Erreur requête serveur, response.status = "..response.status) end end end, error = function(err) Trace("orange","Erreur de reception de données, Erreur = ".. err) end }) end if not(ok) then Trace("orange","Erreur dans l'exécution de http:request(Query...") end end Modifié le 15 décembre 2018 par MAM78
Lazer Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 1/ Je ne vois aucune raison pour laquelle il faudrait protéger un appel à http:request(), il s'agit d'une fonction qui s'exécute en asynchrone 2/ Idéalement il faudrait protéger l'appel à json.decode() à chaque fois qu'on décode un JSON provenant d'une source qu'on ne maitrise pas.... c'est à dire presque tout le temps en fait ! 3/ Comme dit ci-dessus, et plusieurs fois sur le forum, c'est une fonction asynchrone, la suite de ton code doit s'exécuter à l'intérieur. 4/ Met des traces de partout, et constate par toi même ce qui se passe en cas de timeout... de mémoire ça doit être la fonction error() qui est exécutée.
MAM78 Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 Merci Laser pour tes réponse, Pour les scènes le fonction Net.FHttp() n'étant pas disponible, je suis obligé d'utiliser HTTPClient(). 1) Sont-elle toutes le 2 deux asynchrone ? il y a 7 minutes, Lazer a dit : 1/ Je ne vois aucune raison pour laquelle il faudrait protéger un appel à http:request(), il s'agit d'une fonction qui s'exécute en asynchrone 2) Tu veux dire que que l'appel à http:request() va me redonner la main alors que sont traitement ne serait pas terminé. C'est bien ce que tu veux dire par asynchrone ? il y a 11 minutes, Lazer a dit : 4/ Met des traces de partout, et constate par toi même ce qui se passe en cas de timeout... de mémoire ça doit être la fonction error() qui est exécutée. 3) C'est ce que je supposais également. Mais comment faire le test ? Ralentir le serveur cible pour que le requête tombe en timeout ?
MAM78 Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 Je viens de trouver ton post sur le sujet : Il y a probablement les réponses mes questions
Lazer Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 1/ Non, seule Net.Fhttp (dispo seulement dans les VD) est syncrhone, elle s'exécute linéairement de façon traditionnelle. 2/ Oui, tu reprends la main tout de suite, donc il FAUT que ton code se termine immédiatement après pour que les fonctions success() et error() appelées en calback par http:request() puisse s'exécuter. C'est pareil que pour la fonction settimeout() en fait. La suite de ton code doit se trouver dans success() 3/ Mettre des fibaro:debug() de partout dans ton code, et faire une requête vers un serveur qui ne répond pas. Ou qui est trop lent à répondre, utilise pour cela l'option timeout décrite dans mon tuto que tu as trouvé.
MAM78 Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 (modifié) 1) Il n'est donc pas possible de créer une fonction générique HTTPClient() puisque chaque fois que l'utilise il faut qu'elle contienne les traitements spécifique que l'on veut exécuter. C'est bien ça ? 2) est-ce que l'on peut dans success() lancer une autre fonction HTTPClient() ? 3) si oui à la question précédente ça devient vite compliquer à programmer, je prends l'exemple suivant : On se connect à un serveur via un ID de connection mais que celui-ci ne fonction plus On se reconnect au un serveur via un login et mot de passe pour obtenir un nouvel ID On se reconnect au au serveur serveur via le nouvel ID et l'on execute une requête pour obtenir des premiers infos via une API. On se reconnect au au serveur serveur via le nouvel ID et l'on execute une requête pour obtenir des deuxièmes infos via une API. On se reconnect au au serveur serveur via le nouvel ID et l'on execute une requête pour obtenir des Xièmes infos via une API. Cela veux dire que le code doit être structuré de façon à cascader chacune des étapes ? Ca m'a l'air bien lourd ou il y a quelque chose qui m'échappe. 4) Comment s'assurer que l'appel à une fonction HTTPClient() est terminée pour poursuivre les traitements suivants ? Modifié le 15 décembre 2018 par MAM78
Lazer Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 1/ Si c'est possible si tu lui passes des arguments spécifiques. Regarde comment j'ai traité ce sujet dans la scène MusicCast. 2/ Normalement oui, mais tu peux le tester. Mais si tu veux traiter le point 1, il vaut mieux appeler une fonction qui ensuite appellera à son tour HTTPClient. Encore une fois, voir MusicCast. 3/ Le cas du login est traité dans la scène de détection de présence via Unifi. Il faut effectivement bien structurer son code. 4/ Tu ne peux pas, relis mon tuto.... je ne vais pas me répéter
MAM78 Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 il y a 22 minutes, Lazer a dit : 4/ Tu ne peux pas, relis mon tuto.... je ne vais pas me répéter En faite ma question j'aurais du préciser ma question. Comment ext-ce que l'on fait dans le cas d'une de l'appel à la fonction HTTPClient() dans une boucle ?
Lazer Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 Tu ne peux pas, il faut revoir tout ton code.... c'est la fonction success() appelée en callback de HTTPClient() qui doit à son tour effectuer la suite des actions. On peut imaginer passer un tableau de paramètre avec la liste des actions à effectuer, et un pointeur pour savoir où on en est.
MAM78 Posté(e) le 15 décembre 2018 Signaler Posté(e) le 15 décembre 2018 (modifié) Je viens de regarder ta scene : Yamaha MusicCast - Scene v1.0.lua et ses VD associé. C'est exactement cette mécanique que je souhaite mettre en place une scene qui : Sollicite une API via des requêtes HTTPClient() reçoit des ordres (action) en provenance d'un ensemble de VD met à jour des labels de ses même VD en fonction des ordres reçus Maintenant, je vais devoir comprendre son fonctionnement pour l'adapter à mon besoin. C'est une très bonne base de départ Mais j'ai un peu de mal a comprendre le fonctionnement des lignes ci-dessous dans tes fonctions ( getAPI() et getAPI() ), notamment la ligne : setTimeout(function() callback(verb, jsonTable) end, 0) -- Execute callback function if callback and type(callback) == "function" then if debug then Message("purple", "getAPI() : callback...") end setTimeout(function() callback(verb, jsonTable) end, 0) end Je suppose que pour comprendre qu'il faut l'associer à l'exemple du code suivant : if debug then Message("pink", "link() : call postAPI(setClientInfo)") end setTimeout(function() postAPI("/YamahaExtendedControl/v1/dist/setClientInfo", "setClientInfo", link, {group_id=group_id, zone={_parameters[client_vd_s_id].zone}}, client_ip, client_port) end, 0) elseif verb == "setClientInfo" then Je l'impression que c'est bien là le fond du sujet évoqué précédemment ? Pourrais-tu STP m'expliquer un peu le principe de fonctionnement et notamment au regard de nos échanges précédents ? Modifié le 15 décembre 2018 par MAM78
MAM78 Posté(e) le 16 décembre 2018 Signaler Posté(e) le 16 décembre 2018 J'ai avancé sur mon code, mais je n'arrive à faire fonctionner les appels via la fonction setTimeout. Elle n'execute pas la fonction les appels aux fonction getAPI() ou postAPI(). SI je prends l'exemple de ta fonction : power ci-dessous, dans la ligne : setTimeout(function() getAPI("/YamahaExtendedControl/v1/".._parameters[VD_s_id].zone.."/setPower?power=".._value, "setPower", power) end, 0) l'appel de la fonction getAPI ne s'execute pas. J'ai mis des traces au début de la fonctions getAPI() mais elles n'apparaissent pas. Si j'enlève la partie setTimeout(function() de la façon suivante : getAPI("/YamahaExtendedControl/v1/".._parameters[VD_s_id].zone.."/setPower?power=".._value, "setPower", power) dans ce cas, je rentre bien dans la fonction getAPI (avec affichage de mes traces), mais là, l'appel à la fonction : httpClient:request("http://" .. ip .. ":" .. tostring(port) .. url, { ne provoque aucun retour, ni dans success, ni error. Je ne vois vraiment pas d'où vient le PB. Tu pourrais STP m'indiquer la cause ? local function power(verb, data) if not verb then if debug then Message("pink", "power() : call getAPI(setPower)") end setTimeout(function() getAPI("/YamahaExtendedControl/v1/".._parameters[VD_s_id].zone.."/setPower?power=".._value, "setPower", power) end, 0) elseif verb == "setPower" then Success() else Die('Warning : verb "' .. (verb or "???") .. '" unknown') end end -- function
MAM78 Posté(e) le 16 décembre 2018 Signaler Posté(e) le 16 décembre 2018 (modifié) @Lazer Laisse tomber mon message ci-dessus. J'ai trouvé J'ignore pourquoi, mais lorsque je lance la scène depuis un VD, ça fonctionne Mais lorsque je lance la scène en manuel, ça ne marche pas. Je sais ce n'est pas l'objet de ce type de scène qui doivent être lancé depuis une autre scène ou VD. Mais maintenant, je m'arrache les cheveux pour construire la structure du code pour que les enchainements se fassent bien Modifié le 16 décembre 2018 par MAM78
Lazer Posté(e) le 16 décembre 2018 Signaler Posté(e) le 16 décembre 2018 Désolé, pas dispo plus tôt. Bon tu avances, c'est bien Aucune idée pour le lancement manuel, c'est étrange, ça ne devrait pas être différent d'un appel depuis le VD, car c'est bien un lancement manuel qu'il fait. La différence, c'est que le VD passe des paramètres, tandis que ton lancement manuel ne donne aucun paramètre. Dans ton code, il faut que tu récupères et testes les paramètres de la scène dès le début de son exécution..... il y a un tuto pour ça aussi sur le forum
MAM78 Posté(e) le 16 décembre 2018 Signaler Posté(e) le 16 décembre 2018 (modifié) J'ai un peu de mal à comprendre comment organiser le code pour executer l'enchainement suivant chaque fois que la scène est appelée par une action. On se connect au serveur pour récupérer des paramètres de l'API nécessaire pour se connecter au serveur, si la requête est bone, on passe au point 2 On se reconnect au serveur via un ID de connection stocker dans une VG mais que celui-ci ne fonctionne pas/plus ou qu'il n'est pas encore renseigné dans la VG l'on passe au point 2.1 sinon au point 3 On se reconnect au serveur via un login et mot de passe pour obtenir un nouvel ID qui est stocker dans une VG On se reconnect au serveur serveur via l'ID et les paramètres de l'API et l'on execute une requête pour soit : (En fait mon action demandé pas le VD) obtenir des infos de l'API executer d'une fonction de lAPI modère une propriété de l'API Sachant que les paramètre de l'API peuvent changer dans le temps, idem pour l'ID, il peut ne plus être valable après un certain temps. Autant les paramètre d'API, je pourrais les charger dans une VG depuis le main des VD puisqu'il n'est pas nécessaire de s'identifier sur le serveur pour obtenir ces paramètres. Mais pour l'ID je souhaiterais éviter de devoir mettre dans chacun des mes VD mon login et mot de passe pour générer un nouvel ID et le stocker dans une VG. Sachant comme tu t'en doute, l'objectif principal est de mettre tous (ou le maximum) le code lié à l'API dans la scène et alléger de fait les VD au maximum. a) Compte-tenu mode asynchrone, est-ce que cela signifie que pour chaque des actions lancées par les VD, je dois dans la scène créer un fonction correspondante qui devra contenir l'ensemble de la séquence énoncée ci-dessus ? Excepte la recherche des paramètres si elle est ramenée dans le main du VD (ce que souhaiterais néanmoins éviter b) Est-ce qu'il y une limite du nombre d'imbrications des séquences d'appels à l'API via des requêtes HTTPClient() ? c) Comment organiser ces imbrications avec le principe de callback des fonctions ? Nota : c'est vraiment lourdingue de ne pas avoir mis à disposition la fonction Net.FHttp() dans les scènes. Il font ch... chez Fibaro. Cela nous oblige du coup à monter du code d'une complexité, s'il on veut limiter sa redondance Modifié le 16 décembre 2018 par MAM78
Lazer Posté(e) le 16 décembre 2018 Signaler Posté(e) le 16 décembre 2018 a) euh là je ne suis pas certain de bien comprendre ce que tu veux faire.... b) aucune idée ! En tout cas perso je n'ai pas été limité. Il faut tester. c) idem que point (a), ce que tu veux faire n'est pas clair pour moi. Mais de ce que tu décris, je dégage 2 choses principales : pouvoir configurer tous les paramètres en un point unique, par exemple la Main Loop du VD, laquelle se charge ensuite de stocker ces paramètres dans une variable globale (à grand coup de json.encode()) Toute cette logique est utilisée dans mon VD MusicCast, entre la Main Loop, ses Boutons, et la scène unique (je précise bien scène unique, car cette même scène est appelée par TOUS les boutons de TOUS les VD (un VD par enceinte/ampli à domotiser)). Plus précisément : dans la Main Loop du VD : il y a toute la logique de création de la VG, du stockage des données, et même une vérification périodique de sa validité (protection contre les N/A bien connus qui se produisent lorsque l'utilisateur va enregistrer manuellement le panneau de variable). il y a également, en bonus, la détection automatique de l'ID de la scène, ce qui évite à l'utilisateur de devoir le renseigner manuellement dans chaque bouton de VD : Appel de la scène avec des arguments dans la scène : récupération des arguments ==> Donc pour moi, il n'y a pas vraiment de difficulté sur ce point là, tu peux simplement récupérer et adapter ce que j'ai fait. enchainer les actions asynchrones dans la scène entre les appels aux fonctions HTTPClient() et settimeout() Là encore, tout cela est utilisé dans la scène MusicCast, avec tout un tas de paramètres passés en argument des fonctions, afin que prendre les bonnes décisions (quelle action effectuer ensuite, etc). Justement là comme je ne comprends pas ce que tu veux faire, c'est à toi de bien comprendre la logique de fonctionnent, et de le traduire pour tes propres actions. ==> Là, c'est à toi de jouer
MAM78 Posté(e) le 16 décembre 2018 Signaler Posté(e) le 16 décembre 2018 (modifié) Tout ce que tu viens de dire je l'avais bien compris. Et c'est bien sur tes VD et ta Scène MusicCast que je capitalise. J'ai garder la logique d'ensemble. Dans ton code MusicCast tu n'utilises pas non plus le Main Loop des VD pour solliciter l'API. Tout est dans ta scène et c'est bien ça que je cherche à reproduire. Mettre tout le code concernant l'API dans la Scène. Mon questionnement vient en fait sur l'écriture d'une fonction (Action) dans la scène, lorsque celle-ci nécessite des appels à l'API en cascade à l'intérieur de celle-ci. Cf. les différentes étapes du traitement que j'exposais précédemment, dont chacune des étapes doit correspond re à une fonction afin de pouvoir utiliser le mécanisme de callback pour connaitre le résultat de la fonction (étape). Effectivement, de part le mécanisme de traitement asynchrone, c'est difficile à expliquer. Merci néanmoins pour tes explications précieuses Modifié le 16 décembre 2018 par MAM78
Messages recommandés