Aller au contenu

Velux ... intégration avec HC2, un peu de teasing :-)


Messages recommandés

Effectivement le wimove semble parfait merci je ne connaissais pas.

Pour l’assurance tu as de la chance, la notre nous impose la fermeture complète peut importe la durée de l’absence .

Après je me pose la question juste par rapport à la prise en charge par l’assurance en cas de problème, parce que niveau effraction je ne compte sur rien quand je vois mes voisins en pleine après-midi en semaine pendant les courses (1h30 Max) avec quasiment tous les voisins présents, ouverture de la grosse porte d’entrée au pied de biche + porte de garage .


Envoyé de mon iPhone en utilisant Tapatalk

Lien vers le commentaire
Partager sur d’autres sites

ah mince :mellow:

 

Pour l'assurance, on paye très cher,en gros c'est un des contrat les plus élevé qu'on a trouvé.

Chaque année je fais le comparatif sur les moteurs genre Assurland, on cochant toutes les cases pour avoir le maximum de protection, et même en sélectionnant la meilleure offre (pas la moins chère donc...), le niveau de protection reste inférieur à la notre.

Bref, clairement pas rentable tant qu'il n'arrive rien, mais c'est le prix de la tranquillité.

Puis bon, dans le 93, dans une rue pavillonnaire où tous les voisins se sont fait visiter.... voilà quoi.

Lien vers le commentaire
Partager sur d’autres sites

Mince, c'est chaud chez vous :)

Moi la notre c'est volet fermé si plus de 48 ou 72h, je ne sais plus, donc pas le week-end. Et elle couvre tout de chez tout, pour un prix très correct. D'ailleurs j'ai découvert un nouveau truc: Ma fille a voulu descendre de l'étage avec sa tirelire, un gros truc, et bien sûr boom, en plein sur la baguette alu d'une des marches.

J'ai demandé à ma femme de voir avec l'assurance, et aucun souci, ils couvrent tout, achat des carreaux, poseur etc.

Lien vers le commentaire
Partager sur d’autres sites

Bah oui c'est chaud, on est des gros durs nous :P

 

Autre truc sympa aussi, mon assureur me laisse faire le ramonage moi même, pas obligé de payer et d'attendre la prestation d'un "pro", qui fera de toute façon un travail d'une qualité inférieure au miens.

La plupart des assureurs imposent le passage d'un pro avec certificat à l'appui.

Lien vers le commentaire
Partager sur d’autres sites

L’unique cas ou le ramonage est non négociable et obligatoire par un professionnel pour être couvert en cas de problème c’est pour une chaudière Gaz atmosphérique et peut-être aussi pour une chaudière fuel mais pas pour un risque de feu mais surtout de refoulement des gaz de combustion.

Après mon assurance réclame aussi le passage d’un Pro (enfin une facturette lol) pour le ramonage cheminée / poêle, je ne prends pas beaucoup de risques à le faire moi même avec le poêle à pellets avant avec la cheminée c’était la bûchette qui va bien avec le certificat et le ramonage moi même. C’est efficace mine de rien la bûchette


Envoyé de mon iPhone en utilisant Tapatalk

Lien vers le commentaire
Partager sur d’autres sites

Et voilà, j'ai enfin reçu le klf-200...je vous fais donc comme promis un petit retour.

Lorsque mon intégration sera finie, je ferai un tuto un peu plus joli et structuré que celui-ci ;)

 

premier constat, Velux n'est pas concerné par le réchauffement de la planète...  il y a exactement 27 petits manuels livrés avec... il y a même des langues que je ne connais pas :lol:

plus un autre petit manuel (4 pages) pour se connecter via pc.

 

IMG_1765.JPG.e7c28ffa937a9652e8df42e3de46d399.JPG

 

le câblage pour l'ensemble des entrées/sorties est fourni (fils rouges et noirs pour les entrées, bleu et blanc pour les sorties

 

Lorsqu'on démarre le KLF-200, il crée un point d'accès wifi sur lequel il suffit de se connecter pour ensuite pouvoir modifier tous les paramètres, comme par exemple lui assigner une adresse IP fixe, ce qui permet de se connecter sur le réseau avec un simple browser.

 

La première étape est d'importer les produits Velux que l'on veut manipuler. Pour ce faire il faut faire une copie des produits déjà installés sur une autre télécommande (KLR200 dans mon cas)

Une fois les produits connus par le KLF200, on peut soit créer ce qu'ils appellent des programmes, c'est à dire des actions sur les produits. Par exemple "Ouvrir toutes les fenêtres", ou "Fermer toutes les fenêtres".

La création de ces programmes se fait aussi ç l'aide de la télécommande...  le KLF200 se met en mode enregistrement et enregistre les différentes actions générées par la télécommande.

 

On peut aussi modifier le comportement standard des actions pour chaque contact sec en entrée. En standard, un contact ouvre, un autre ferme, un contact de plus de 1.5 seconde ouvre partiellement jusqu'à ouverture du contact. On peut associer un programme à une entrée par exemple.

 

J'ai aussi configuré pour test une sortie (en mode contact sec si résultat = ok).

Le tout fonctionne bien, je dois encore voir maintenant pour configurer plus de produits (stores et volets), pour l'instant je n'ai configurer que les moteurs.

 

il me reste à créer une scène pour tester l'api mais là j'ai besoin de l'équipe :)  

 

en gros il faudrait créer 1 scène avec le login, l'action,et le logout.

 

j'ai trouvé cet exemple sur le net, mais je ne me sens pas trop capable de le transcrire en LUA... (surtout qu'à la moindre erreur tout se bloque, je viens de bloquer ma commande klr200 et je n'arrive pas à la redémarrer :lol:

 

 

Authenticate

POST /api/v1/auth HTTP/1.1
Host: 192.168.0.1
Content-Type: application/json;charset=utf-8
Content-Length: 51
Connection: close

{"action":"login","params":{"password":"velux123"}}

Run a program

POST /api/v1/scenes HTTP/1.1
Host: 192.168.0.1
Content-Type: application/json;charset=utf-8
Authorization: Bearer bBbpXgBfTlw9LQwytyH5Cw==
Content-Length: 34
Connection: keep-alive

{"action":"run","params":{"id":2}}

Identify a product

POST /api/v1/products HTTP/1.1
Host: 192.168.0.1
Content-Type: application/json;charset=utf-8
Authorization: Bearer bBbpXgBfTlw9LQwytyH5Cw==
Content-Length: 50
Connection: close

{"action":"identify","params":{"id":5,"time":254}}

 

il y a aussi celui-ci...

!/bin/sh

programm=$1
token=$(curl -H "Accept: application/json" -H "Content-Type: application/json;charset=utf-8" -d '{"action":"login","params":{"password":"velux123"}}' -s hXXp://192.168.x.x/api/v1/auth | tail -n +2 | jq -r '.token')

curl -H "Content-Type: application/json;charset=utf-8" -H "Authorization: Bearer $token" -d "{\"action\":\"run\",\"params\":{ \"id\":$programm}}" -s hXXp://192.168.x.x/api/v1/scenes

curl -H "Content-Type: application/json;charset=utf-8" -H "Authorization: Bearer $token" -d '{"action":"logout","params":{}}' -s hXXp://192.168.x.x/api/v1/auth

 

 

Bon, maintenant je vais essayer de réparer ma télécommande :angry:

 

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

@pepite oui, j'ai un user/password, et le token, je crois que c'est le retour de l'appel au login

je n'ai rien branché en définitif, j'ai juste fait quelques tests, les câbles sur la photo ils sont fournis avec le boitier, directement sur des connecteurs qu'il suffit d'enficher.

oui, je pensais aussi au Net.HTTPClient dans une scène, j'étais justement en train de regarder un exemple avec un POST trouvé sur le forum 

 

@Nico bah, il n'est pas si grand que ca, il doit faire 12 cm * 12 cm. Avec le navigateur tu peux te connecter sur le boitier, créer des programmes, activer ces mêmes programmes, modifier les paramètres, le réseau, etc, et paramétrer les actions relatives aux entrées / sorties

 

Lien vers le commentaire
Partager sur d’autres sites

@Cardane

 

OK. 

J'avais commence un couple Scene/VD pour interagir avec un thermostat Nest. 

 

Si ca peut t'aider, c'est du Bearer aussi pour l'authentification

-- ---------------------------------------
-- Recuperation des datas "thermostats" --
-- ---------------------------------------
function GetDataThermostats()
    httpNest:request(URL, { 
        options = {
            method = 'GET',
               headers = {
                   ["Content-Type"] = "application/json",
                ["Authorization"] = "Bearer "..access_token
              },
        },
        success = function(response) 
            tools.debug(json.encode(response))
            tools.info("Get status Thermostats : " ..response.status)
                if tonumber(response.status) == 200 then
                    if response.data and response.data ~= "" then
                        local jsonTable = json.decode(response.data)
                        local CurrentTemperature = jsonTable.ambient_temperature_c
                        TargetTemperature = jsonTable.target_temperature_c
                        HvacMode = jsonTable.hvac_mode
                        local HvacState = jsonTable.hvac_state
                        --local FanTimerDuration = jsonTable.fan_timer_duration
                         tools.info("NestCurrentTemperature : " ..CurrentTemperature.. " °C")
                         tools.info("NestSetPoint : " ..TargetTemperature.. " °C")
                         tools.info("NestMode : " ..HvacMode)
                         tools.info("NestState : " ..HvacState)
                         --tools.info("Fan_timer_duration : "..FanTimerDuration)
                         setLabel(idVD_Nest, "NestTmp", CurrentTemperature.." °C")
                         setLabel(idVD_Nest, "NestSetPoint", TargetTemperature.. " °C")
                         setLabel(idVD_Nest, "NestMode", HvacMode)
                         setLabel(idVD_Nest, "NestEtat", HvacState)
                         setLabel(idVD_Nest, "NestMaj", date.. " - " ..heure)
                     end
                 end
        end,
        error = function(error) tools.error("Erreur : " ..error) end,
    })
end


function PutDataStructures()
    httpNest:request(URLStructures , {
        success = function(response)
            tools.debug(json.encode(response))
            if tonumber(response.status) == 200 then
                tools.info("PUT Structures OK : " ..date.. " - " ..heure)
            end
        end,
        error = function(err)
            tools.error("Erreur de PUT Structures : " ..date.. " - " ..heure)
        end,
        options = {
            method = 'PUT',
            headers = {
                ["content-type"] = "application/json",
                ["Authorization"] = "Bearer "..access_token
                 },
            data = datas
            --data = "{\"away\":\"away\"}"
            }
    })
end

 

Lien vers le commentaire
Partager sur d’autres sites

@pepite à ton avis, pour la fonction de login, sur base de l'exemple que j'avais mis ci-dessus, est-ce que ce qui suit te parait correct ?

 

je préfère être certain avant de tester, cette interface m'a l'air assez capricieuse :-)

 

--[[
%% properties
%% events
%% globals
--]]
     
local url = 'http://192.168.xxx.yyy/api/v1/auth HTTP/1.1'
local datas = '{"action":"login","params":{"password":"PASSWORD"}}'

local httpClient = net.HTTPClient()
httpClient:request(url , {
        success = function(response)
                    print (response)
                end,
        error = function(err)
                    print('error = ' .. err)
                end,
        options = {
                method = 'POST',
                headers = { 
                        ["content-type"] = 'application/json',
                        ["connection"] = 'close'
                          },
                data = datas
            }
});
Modifié par Cardane
Lien vers le commentaire
Partager sur d’autres sites

Salut @Cardane

Peut-etre quelquechose comme ceci, mais sans certitude. Ca fait un bon début. Après va falloir faire appel aux experts du code ;-).
Ce qui est etonnant, c'est qu'on ne trouve rien d'officiel sur l'API de ce KLF200

-- Authentification
local ip = "192.168.xxx.yyy"
local url = 'http://'.. ip .. '/api/v1/auth'
local datas = '{\"action\":\"login\",\"params\":{\"password\":"PASSWORD"}}'

local klf = net.HTTPClient()
klf:request(url , {
        success = function(response)
                    print (response)
                end,
        error = function(err)
                    print('error = ' .. err)
                end,
        options = {
                method = 'POST',
                headers = {
                   ["content-type"] = 'application/json, charset=utf-8'
                   },
                data = json.encode(datas)
            }
})
-- Run program
local ip = "192.168.xxx.yyy"
local url = 'http://'.. ip .. '/api/v1/scenes'
local program = "xxx"
local datas = "{\"action\":\"run\",\"params\":{ \"id\":"..program.."}}"
local access_token = "xxxxxxxxx"

local klf = net.HTTPClient()
klf:request(url , {
        success = function(response)
                    print (response)
                end,
        error = function(err)
                    print('error = ' .. err)
                end,
        options = {
                method = 'POST',
                headers = {
                   ["content-type"] = 'application/json, charset=utf-8'
                   ["Authorization"] = "Bearer "..access_token
                   },
                data = json.encode(datas)
            }
})
-- logout
local ip = "192.168.xxx.yyy"
local url = 'http://'.. ip .. '/api/v1/auth'
local datas = '{"action":"logout","params":{}}'
local access_token = "xxxxxxxxx"

local klf = net.HTTPClient()
klf:request(url , {
        success = function(response)
                    print (response)
                end,
        error = function(err)
                    print('error = ' .. err)
                end,
        options = {
                method = 'POST',
                headers = {
                   ["content-type"] = 'application/json, charset=utf-8'
                   ["Authorization"] = "Bearer "..access_token
                   },
                data = json.encode(datas)
            }
})

 

Modifié par pepite
Lien vers le commentaire
Partager sur d’autres sites

il y a 11 minutes, pepite a dit :

Ce qui est etonnant, c'est qu'on ne trouve rien d'officiel sur l'API de ce KLF200

Ca t'étonne toi ? Tu veux que je te rappelle qui est la fabricant de ce KLF200 ? Et sa politique commerciale ?

 

Je trouve que c'est déjà un progrès gigantesque d'avoir ce module permettant d'enfin ouvrir IO sur le monde extérieur, via une passerelle locale sans cloud.

 

Il faudrait qu'un installeur agréé obtienne la doc et nous la donne en privé.... :)

Lien vers le commentaire
Partager sur d’autres sites

@pepite et @Lazer   comme je disais, l'API n'est pas documenté, et il semble que bien entendu ce soit volontaire de la part de Velux. J'ai discuté avec un installateur/distributeur, et il était à peine au courant de l'existence de ce boitier. Sur la page du site Velux, il apparait bien dans la partie professionnelle, mais avec très peu de d'explication. Après, comme le gars m'a dit, c'est pas leur boulot de faire de la domestique et de l'intégration, ils n'y comprennent rien, et donc l'installation via la voie câblée est déjà un maximum pour eux...  alors faut pas leur parler d'attaquer un API non documenté :D

 

Concernant le bout de code ci-dessus, merci beaucoup Petite, mais je me pose plusieurs questions.

1. Si j'ai bien compris, le net. HTTPClient fonctionne en mode asynchrone, donc je ne peux surtout pas enchainer les trois bout de code à la suite l'un de l'autre.

2. Toujours si j'ai bien compris, il faudrait donc que je code pour le "Run" soit dans la fonction du net.HTTPClient de login, et le code du logout dans la fonction du net.HTTPClient du run ??? J'ai loupé quelque chose ?

3. En fait l'access token est le retour de l'appel au login, donc je suppose que c'est le 'response' du net.HTTPClient pour le login , que je peux utiliser et coller derrière le Bearer ????

 

J'ai tout faux ???  ou un petit peu de vrai ???  :)

 

(pffffff, ca me rappelle ma jeunesse quand je passais des nuits à pondre du code...  je viens de me prendre un coup de vieux là :20:)

 

 

Lien vers le commentaire
Partager sur d’autres sites

En fait, Je suis parti des exemples que tu avais postés et de ce que j'aurais essayé en le transcrivant en LUA pour chacun. ce qui est sur c'est que l'API d'authentification n'est pas la même que pour lancer un programme. (d'ailleurs qu'est-ce que ce programme ? )

 

Ensuite Bearer est nécessaire pour utiliser ton token. Ce que je n'ai pas compris c'est comment le récupérer. Dans le shell que tu as posté il fait un tail dessus :

 - tail -n +2 : commence après la 2eme ligne je crois

 - jq -r : permet de recuperer le string de la reponse du json et de l'avoir en sortie sans qu'il soit formaté en json.

 

Donc pour moi la réponse à l'authentification est ton token.

 

L'enchainement ou non des commandes, heuuu

En fait j'en ferais des fonctions je pense.

Lien vers le commentaire
Partager sur d’autres sites

@pepite alors, un programme, c'est le nom utilisé par Velux.

Sur le KLF-200, tu peux, via l'interface web, créer toutes une série de 'programmes'. Un programme simple peut-être "Ouverture du Velux de gauche à 50 %". Tu te mets en mode enregistrement, tu actionnes ton Velux pour l'ouvrir à 50% et tu stoppes ton enregistrement....  ton programme est créé.

L'avantage, c'est que tu peux faire autant de choses que tu veux sur différents produits, tant que tu enregistres, c'est bon. Par exemple, j'ai créé pour test un programme qui positionne les stores à 40%, ouvre 2 Velux de la première pièce à 20 %, 3 autres à 50 % et ceux d'une autre pièce à 100 %. C'est ce "programme" que tu peux appeler via l'API, soit en l'appelant par son nom, soit par son numéro. 

 

Bon, je vais faire quelques tests ce soir, si je bousille l'interface je serai bon pour faire un reset et tout recommencer. 

Je maîtrise la fonction net.HTTPClient, je veux juste être certain que la partie de code que je vais écrire après le "success = fonction (response)" est bien du code qui sera exécuté APRES la fin du call. De cette manière, je récupère le token (qui comme tu dis doit être 'response'), je fais un appel pour le 'run', et ensuite pour le logout.

 

Le côté chiant de cet API, c'est que si je fais un call pour le login et que ensuite je fais une connerie, le boitier est bloqué parce qu'une connexion existe et n'est pas terminée. (Ils ne gèrent pas les connexions multiples, faut pas trop leur en demander... )

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

Bon, je viens de faire un test tout simple avec juste le login....

 

le print (response) affiche :

 

table: 0x8d2aa10

 

le bon point c'est que je ne suis pas en erreur :2:

 

mais alors maintenant, qu'est-ce que je fais avec cette 'response' pour trouver mon token ?  (qui doit ressembler à un truc comme bBbpXgBfTlw9LQwytyH5Cw== )

donc je suppose que je dois faire l'équivalent de tail -n +2 | jq -r  sur response ?  comment on fait ca en lua ?????????  

Lien vers le commentaire
Partager sur d’autres sites

Je suppose que ton token n'est pas dans la réponse elle-même, mais dans l'entête de la réponse (c'est là que se trouvent les cookies par exemple)
Avec net.HTTPClient () tu as accès à l'entête (header), donc il faut que tu parcours pour essayer de trouver l'info que tu cherches.

Lien vers le commentaire
Partager sur d’autres sites

Regarde ma scène LUA de détection de présence via Unifi Controller pour voir un exemple de code pour aller lire le cookie dans l'en-tête

 

alors toi ce n'est probablement pas un cookie que tu cherches, mais ça te donnera une piste pour accéder aux entêtes.

Lien vers le commentaire
Partager sur d’autres sites

@pepite @Lazer  ca progresse , mais j'ai encore un tout petit peu besoin de vous....:(

je suis parvenu à voir le token, et donc à faire un login puis un logout avec le code suivant :

local ip = "192.168.1.33"
local url = 'http://'.. ip .. '/api/v1/auth'
local datas = '{"action":"login","params":{"password":"velux123"}}'

local klf = net.HTTPClient()
klf:request(url , {
        success = function(response)
      				print ("Je suis dans response")
      				fibaro:debug(response.data)
       				local jsonTable = json.decode(response.data)
      				fibaro:debug(jsonTable.token)
                end,
        error = function(err)
      				print ("Je suis dans err")
                    print('error = ' .. err)
                end,
        options = {
                method = 'POST',
                headers = {
                   ["content-type"] = 'application/json, charset=utf-8'
                   },
                data = datas
            }
})

le seul problème qu'il me reste est le suivant...  le fibaro:debug(response.data) affiche ceci :

 

image.png.f3ac434a80db83a5fbeefb94a4ab7da7.png

 

je peux donc visualiser le token et le noter, mais ce que je ne comprend pas c'est la deuxième ligne qui affiche le )]}',

et aussi pourquoi le fibaro:debug(jsonTable.token) ne fonctionne pas ???

 

une fois ce problème résolu, c'est bon, je peux mettre le code au propre et créer une scène complète avec un login, un run et un logout

 

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

il y a 17 minutes, Cardane a dit :

local jsonTable = json.decode(response.data) fibaro:debug(jsonTable.token)

je ferais ligne par ligne pour savoir après dans le "je suis dans le response

 

et j'assurerais le coup avec data = json.encode(datas)

 

Il y a une erreur fatale aussi ;-)

 

PS : j'aurais commencé par un fibaro:debug(json.encode(response))

Modifié par pepite
Lien vers le commentaire
Partager sur d’autres sites

On dirait bien que ton response.data est mal formé, donc le json.decode(response.data) plante irrémédiablement.

 

Il faudrait trouver le moyen de "nettoyer" le response.data avant de le passer à json.decode, mais là tout de suite, je ne vois pas trop comment

 

EDIT : oui Pepite à raison, il faut plus décomposer tes debugs pour mieux comprendre ce qui se passe

Lien vers le commentaire
Partager sur d’autres sites

×
×
  • Créer...