mulderonline Posté(e) le 8 novembre 2014 Signaler Posté(e) le 8 novembre 2014 Bonjour, Je cherche a passer une valeur par une url quand un detecteur de mouvement de la Hc se declence http://(HS3 URL)/HomeSeer_REST_API.aspx?function=setdevicevaluebyid¶m1=(Device Reference ID)¶m2=(Value you want to set) Je suis parti d'une scene en mode bloc pour transformer en lua Merci
mulderonline Posté(e) le 9 novembre 2014 Auteur Signaler Posté(e) le 9 novembre 2014 J'avance tout doucement. Je veux executer une url en passant des valeur quand mon detecteur 137 detecte quelque chose: --[[ %% properties 137 value %% globals --]] local value=tonumber(fibaro:getValue(137, "value")) --local value=60 local hs_id=1018 local startSource = fibaro:getSourceTrigger(); if ( value> 0 ) then -- on crée une instance HC2 et on appel le pc HC2 = Net.FHttp("192.168.1.3:8081"); -- on met a jour le device virtuel distant response = HC2:GET("/Api_Rest/HomeSeer_REST_API.aspx?function=setdevicevaluebyid¶m1="..hs_id.."¶m2="..value) fibaro:debug(response) end Mais j'ai l'erreur suivante: [ERROR] 18:53:20: line 13: attempt to index global 'Net' (a nil value) Si quelqu'un peut jeter un oeil, merci
Lazer Posté(e) le 9 novembre 2014 Signaler Posté(e) le 9 novembre 2014 je crois bien que la fonction Net.FHttp() n'est plus supportée en v4 beta
mulderonline Posté(e) le 10 novembre 2014 Auteur Signaler Posté(e) le 10 novembre 2014 ba mince alors.
Lionel57 Posté(e) le 10 novembre 2014 Signaler Posté(e) le 10 novembre 2014 Hello, la fonction est toujours supportée, mais uniquement dans un module virtuel (enfin je crois pour ce dernier truc). Par ailleurs, la fonction get retourne un tableau donc essaie response, status, errCode = HC2:GET("/Api_Rest/HomeSeer_REST_API.aspx?function=setdevicevaluebyid¶m1="..hs_id.."¶m2="..value)
mulderonline Posté(e) le 11 novembre 2014 Auteur Signaler Posté(e) le 11 novembre 2014 Merci pour cette réponse J'ai modifié le code dela maniere suivante: -[[ %% properties 137 value %% globals --]] local value=tonumber(fibaro:getValue(137, "value")) local hs_id=1018 local startSource = fibaro:getSourceTrigger() if ( value> 0 ) then -- on crée une instance HC2 et on appelle le pc HC2 = Net.FHttp("192.168.1.3:8081") -- on met a jour le device virtuel distant --response = HC2:GET("/Api_Rest/HomeSeer_REST_API.aspx?function=setdevicevaluebyid¶m1="..hs_id.."¶m2="..value) response, status, errCode = HC2:GET("/Api_Rest/HomeSeer_REST_API.aspx?function=setdevicevaluebyid¶m1="..hs_id.."¶m2="..value) fibaro:debug(response) fibaro:debug('Envoi vers Homeseer Mouvement Salon') end J'ai aussi dégagé les ";" qui viennent du mode bloc mais que je retrouve pas dans les tutoriels. Pas de progres l'erreur est sur la ligne 12 HC2 = Net.FHttp("192.168.1.3:8081") [ERROR] 09:17:20: line 12: attempt to index global 'Net' (a nil value) [ERROR] 09:17:21: line 12: attempt to index global 'Net' (a nil value) [ERROR] 09:18:00: line 12: attempt to index global 'Net' (a nil value)
Lazer Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Essaye comme ça : HC2 = Net.FHttp("192.168.1.3", 8081) Tu es en v4.018 ? Si ça ne fonctionne pas, c'est que la fonction est supprimée de cette version comme je le disais.
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Je suis en v4.018 à‡a ne fonctionne pas dans une scène, mais ça fonctionne dans un module virtuel http://www.domotique-fibaro.fr/index.php/topic/1824-commande-lua-netfhttp/?hl=net.fhttp
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Éventuellement, tu crées une variable globale Tu crées une scène basique qui va modifier la valeur de cette variable en cas de détection de mouvement. Tu testes ta valeur globale dans le main loop d'un module virtuel et si la condition est remplie, alors exécution de ton code. Et le tour est joué.
Lazer Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 ah oui c'est vrai dans une scène ce n'est pas supporté. Plus simple : depuis la scène, tu peux directement cliquer sur le bouton d'un module virtuel, ce qui évite de créer une variable globale inutilement, évite une boucle dans un module virtuel qui tourne en rond pour pas grand chose, et surtout permet une réactivité immédiate : fibaro:call(<id>, "pressButton", "1")
mulderonline Posté(e) le 11 novembre 2014 Auteur Signaler Posté(e) le 11 novembre 2014 Merci je vais tenter ca. En attendant pour avancer je passais des messages par mail... pas tres rapide
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Une question Maître Yoda, j'ai lu ça et làque le main loop était gourmand en ressource, parce qu'un appel toutes les 3 secondes. Mais une scène classique, faut bien aussi qu'elle soit lancée pour tester la valeur des triggers. Alors y a t-il vraiment une différence ??? Je pose cette question, parce que je suis en train de programmer un module virtuel pour gérer mon chauffage. Ce module s'appuie sur le panneau de chauffage, pour pouvoir agir facilement sans modifier du code. Mais pour le moment, je n'ai pas trouvé d'autres façons d'accéder au panneau autrement que par l'api. (je pense finir ce soir et publier mon code). Mais s'il y a un risque de fatiguer nos HC2, peut être faut que je cherche une autre solution...
Lazer Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Le principe de la main loop d'un module virtuel c'est effectivement de boucler automatiquement avec un sleep de 3 secondes. L'idée c'est que si tu effectue tout un tas de vérifications, pour finalement ne rien faire parce que les conditions ne sont pas remplies, alors du as fait travailler le processeur pendant quelques millisecondes pour rien. Multiple ça par le nombre de modules virtuels, et tu fait travailler inutilement la box. C'est pour ça qu'on dit qu'une main loop est gourmande en ressource. A l'opposé, une scène est inactive tant qu'elle n'est pas déclenchée par un événement (trigger). C'est la HC2 qui active la scène uniquement lorsque c'est nécessaire. Attention toutefois, une scène peut aussi comporter une boucle (à programmer soit même, par exemple avec un simple "while true do ....... end" comme le fait GEA de Steven ou d'autres scènes). A ce moment là , on en revient au principe de fonctionnement d'une main loop de module virtuel. Le truc c'est qu'il y a des situations où on ne peut pas faire autrement que d'avoir une boucle infinie, que ce soit dans un main loop ou une scène. Par exemple : de nombreuses variables à gérer, dont on doit conserver la valeur d'un passage à un autre dans le code... Il serait trop fastidieux de stocker tout ça en variables globales. Il n'y a donc pas d'autres choix que d'utiliser ces fameuses boucles, et on doit alors coder intelligemment pour éviter de surcharger le processeur. Par exemples : éviter de conserver le sleep(3000) si un sleep(60000) est suffisant, essayer de limiter les tâches à effectuer à chaque passage dans la boucle, éviter de faire appel à des fonctions buggées (Net.FHTTP suivi de json.decode) Après il faut relativiser, un programme correctement écrit ne dure pas plus de quelques millisecondes, donc c'est négligeable, et ce n'est pas çà qui va fatiguer la HC2, qui est relativement puissante. L'exemple du script GEA est un bon exemple de la complexité possible tout en conservant d'excellente performances. Les différents modules virtuels de Krikroff également. Dans ton exemple de panneau de chauffage, tu n'as pas d'autre choix que de faire appel à l'API, donc utilisation des fonctions Net.FHTTP() et json.decode()... et cela plantera forcément au bout de quelques passages dans la boucle. La solution est donc de mettre ta routine principale dans un bouton d'un module virtuel, et la main loop se chargera d'appeler le bouton à intervalle régulier.
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Je t'explique en avant première mon projet. J'ai 2 chaudières, mais comme de plus en plus de monde finalement (beaucoup ajoute un mode alternatif à un mode existant). Le panneau de chauffage, bien fait pour programmer des plages horaires par zone relativement facilement, mais un peu obscure si on veut chauffer qu'une partie de son logement à certaines heures (genre, je veux 21° le matin dans ma petite chambre le matin au réveil, mais pas utile d'avoir une telle température dans tout mon logement). Bref, programmer un module me semblait la seule solution. Par ailleurs, ça me permet de prendre en compte les jours fériés, ma présence ou non dans mon logement. J'ai testé aujourd'hui, à priori, ça fonctionne plutôt bien. Pour chaque zone, j'ai créé une variable prédéfinie, nommée id_Chauf_pièce contenant D_XXX pour définir le déclencheur de chauffage (chauffage ou poêle à pelées), P_pièce pour définir à quelle zone le programme de chauffage se rattache la pièce, T_XXX pour définir la sonde de température de référence et Z_XXX pour définir l'id d'un éventuel vanne Danfoss (Z_000, pas de sonde). Puisqu'il s'agit de chauffage, j'ai mis un sleep à 5 minutes (pas pertinent de tester toutes les 3 secondes). Avant d'ouvrir une rubrique, je te met le code en avant première, s'il y a des commentaires... Je posterai dans quelques jours le code mais il me faut encore commenter tout ça, pour que ça soit plus clair function EnumZone() local a, b, c = 0; local p = { }; local i = 0 ; local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/panels/heating"); a, b = string.find(result, "name", 1); while a do b, c = string.find(result, ",", a + 6); i = i + 1 ; table.insert(p, string.sub(result, a + 7, b -2)); a = b + 1; a, b = string.find(result, "name", a); end return p; end function IdZone(piece) local a, b, c = 0; local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/panels/heating"); a, b = string.find(result, piece, debut); return string.sub(result, a-12, a-10); end function TempActuelle(piece) local a, b, c = 0; local T = ""; local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/globalVariables"); a, b = string.find(result, "id_Chauf_" .. piece, 1); b, c = string.find(result, "T_", a); T = string.sub(result, b + 2, b + 4); return fibaro:getValue(T, "value"); end function TempConsigne(Id) local a, b, c, d = 0; local T, h, heureCourante, e, programme = ""; local jour = ""; local currentDate = os.date("*t"); local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/panels/heating?id=" .. Id); if fibaro:getGlobalValue("JourChome") == "Oui" then jour = "sunday" else jour = string.lower(os.date("%A")) end a, b = string.find(result, jour, 1); b, c = string.find(result, "}}", a); programme = string.sub(result, a-1, ; b = 1; if tonumber(currentDate.hour)<10 then e = "0" else e = "" end; heureCourante = e .. currentDate.hour if tonumber(currentDate.min)<10 then e = "0" else e = "" end; heureCourante = heureCourante .. ":" .. e .. currentDate.min for a = 1, 4 do h = ""; b, c = string.find(programme, "hour", b+1); c, d = string.find(programme, ",", ; --fibaro:debug(programme); if tonumber(string.sub(programme, b+6, c-1))<10 then e = "0" else e = "" end; h = e .. string.sub(programme, b+6, c-1); b, c = string.find(programme, "minute", ; c, d = string.find(programme, ",", ; if tonumber(string.sub(programme, b+8, c-1))<10 then e = "0" else e = "" end; h = h .. ":" .. e .. string.sub(programme, b+8, c-1); if h < heureCourante then c, d = string.find(programme, "temperature", ; e, d = string.find(programme, "}", ; T = string.sub(programme, c + 13, e-1); end end return T end function EnumDeclencheur() local a, b = 0; local Declencheur = ""; local Exist = false; local i, j = 0; local D = { }; local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/globalVariables"); a, b = string.find(result, "D_", 1); while a do i = i + 1 ; Declencheur = string.sub(result, a + 2, a + 4); j = 1; Exist = false; while D[j] do if D[j] == Declencheur then Exist = true end; j = j + 1; end if not Exist then table.insert(D, Declencheur) end; a, b = string.find(result, "D_", a + 2); end return D; end function DeclencheurZone(piece) local a, b = 0; local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/globalVariables"); a, b = string.find(result,"id_Chauf_" .. piece, 1); a, b = string.find(result, "D_", a); return string.sub(result, a + 2, a + 4); end function EnumSourceZ(piece) local a, b, c, d = 0; local Cons = { }; local HC2= Net.FHttp("192.168.1.20"); HC2:setBasicAuthentication("admin", "xxxxxx"); local result, status, errorCode = HC2:GET("/api/globalVariables"); a, b = string.find(result, "id_Chauf_" .. piece, 1); a, b = string.find(result, "Z_", a); while a do table.insert(Cons, string.sub(result, a + 2, a + 4)) d = a; a, b = string.find(result, "Z_", a + 2); if a then b, c = string.find(result, "id_Chauf_", d); if b then if b < a then a = nil end; end; end end return Cons; end if fibaro:getGlobalValue("Present") == "Oui" then local i,j,k = 1; local piece = EnumZone(); local declencheur = EnumDeclencheur(); local besoin = {}; local idDeclencheur = {}; local nbDeclencheur = 0; while piece[i] do j = 1; EnumSource = EnumSourceZ(piece[i]); while EnumSource[j] do if EnumSource[j] ~= "000" then fibaro:call(EnumSource[j], "setTargetLevel", TempConsigne(IdZone(piece[i]))) end j = j + 1; end l = 0; for k = 1, nbDeclencheur do if idDeclencheur[k] == DeclencheurZone(piece[i]) then l = k end; end; if l == 0 then nbDeclencheur = nbDeclencheur + 1; l = nbDeclencheur; idDeclencheur[l] = DeclencheurZone(piece[i]) end if tonumber(TempActuelle(piece[i])) < (tonumber(TempConsigne(IdZone(piece[i]))) - 0.7) then besoin[l] = "turnOn" else if not besoin[l] and tonumber(TempActuelle(piece[i])) < tonumber(TempConsigne(IdZone(piece[i]))) then besoin[l] = "standby" else if not besoin[l] then besoin[l] = "turnOff" end end; end; i = i + 1; end; for i = 1, nbDeclencheur do if besoin[i] ~= "standby" then fibaro:call(idDeclencheur[i], besoin[i]) end; end; end; fibaro:sleep(5*60*1000);
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 (j'avoue, j'interroge souvent l'API pour obtenir le même résultat, mais en terme de clarté, de compréhension des fonctions, ça aide beaucoup et vu la rapidité d'obtention des infos, ça ne me semble pas forcément un problème)
Lazer Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Je n'ai pas relu le code en détail, d'autres le feraient mieux que moi (Krikroff, Steven, ...) Puisque tu as un sleep de 5 minutes, il n'y aura aucun problème de performance. Le seul risque, c'est le plantage et donc l'arrêt de la main loop. En effet, tu as tout mis dans la main loop (le code principal et les autres fonctions). A la longue (sur plusieurs jours ou semaines), pour une raison ou une autre, un bug peu arriver et à ce moment là la main loop sera complètement stoppée par sécurité par la HC2. Donc tu n'auras plus de chauffage. Ce qui provoque un plantage à coups sà»r c'est l'emploi de Net.FHTTP() puis GET() et json.decode(). Dans le cas présent tu n'utilises pas le json.decode donc le risque semble limité, mais sait-on jamais ce qui peut se produire... Il serait plus sécurisant de mettre tout ton code dans un bouton de ton module virtuel, et ne conserver que ceci dans la main loop : fibaro:call(fibaro:getSelfId(), "pressButton", "1") fibaro:sleep(5*60*1000) PS : le point-virgule est inutile en LUA, donc je te conseille de les enlever (ou de les mettre à toutes les lignes) pour plus de cohérence. 1
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Je ne suis pas un pro, mais initié par le turbo pascal, donc je me plie tant bien que mal àune certaine discipline, mais là, le compilateur est plus souple...
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 En 4.018, les plantages semblent plus limités (par rapport à4.017). Naïvement, pour moi, jeune adepte de la HC2, du code reste du code... J'ai sans doute beaucoup àapprendre
Lionel57 Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Après, un certain Krikroff ou Steven a dit que c'était aberrant de rebouter sa box pour pallier à certains plantages, donc pour le moment, je me dis que ça reste perfectionable, mais j'ai foi à la HC2
Lazer Posté(e) le 11 novembre 2014 Signaler Posté(e) le 11 novembre 2014 Ouch, le Turbo Pascal j'ai pratiqué il y a très longtemps.... c'était un peu trop strict à mon gout, même si ça ne fait pas de mal. Redémarrer la box ce n'est jamais nécessaire.... (en tout cas, je n'ai personnellement jamais eu besoin depuis 1 an), les seuls reboot sont dus aux mises à jour, ou à mes travaux sur mon installation électrique. Par contre, un virtual device qui plante, ça arrive régulièrement, et avec la méthode que je t'ai donné, c'est fiable à 99,99999% au moins Ca peut aussi planter à cause de son propre code : par ex, on oublie toujours de tester la valeur d'au moins une variable avant de l'employer.
Messages recommandés