Bonjour
Pour mon premier tuto, je vous propose un Module Virtuel pour interfacer la Livebox d'Orange et je vais vous détailler la mise en Å“uvre de l'intégration avec la HC2.
Le module rassemble les informations importantes sur l'état des interfaces, le débit, les statistiques et les différents compteurs d'erreurs. Il permet aussi d'exécuter des commandes simples comme l'activation du Wifi ou le redémarrage de la Livebox.
Prérequis
Une Livebox 2 (Sagem) DSL note: pas pu tester la fibre. J'aimerais bien mais dans moin coin c'est pas avant 2022 ). Une HC2 (code lua testé avec v3.600 et v4.031)
Installation
Télécharger et ajouter le VD (lien en bas de post)
Sur la page de configuration du module, saisir l'adresse ip et le port (80) de la Livebox
Ensuite, il faut paramtètrer le VD, editez le code en debut de page (pour chaque bouttons):
-- Nom d'utilisateur et mot de passe de la livebox
local USER ="admin"
local PASSWORD = "admin"
Le VD retourne trois états possibles: Inconnu, OK et Not OK. Editez les variables pour adapter l'ID des icones:
-- ID des icônes
icon_ok = 1004
icon_nok = 1005
icon_unknown = 1006
Par défault, l'execution du module toutes les 5 minutes est confié à la mainloop du VD qui simule un appui sur le bouton Rafraichir. Simple, mais pour plus de fléxibilité et surtout de plus stabilté je recommande d'utiliser l'excellent GEA avec la ligne ci-dessous (à adapter). Dans ce cas, noubliez pas de supprimer le code dans le mainloop du VD.
-- Mise à jour état connexion Internet
GEA.add(true , 5*60, "",{{"VirtualDevice", id["VD_LIVEBOX"], "1"},{"VirtualDevice", id["VD_LIVEBOX"], "7"},{"Repeat"}})
Le VD n'utilise pas de Variable Globale car je n'ai pas de scénario qui necessite un retour sur l'état de la connexion internet mais c'est juste une ligne de code à ajouter:
fibaro:setGlobal('test', Livebox.WANStatus.LinkState)
Comment ca marche ?
c'est la section pour les geeks. Je partage ici le resultat de mes bidouilles (et saut d'humeur) à propos de l'API Livebox
Fonctionnement de l'API Orange/Sagem:
En regardant d'un peu plus près les paquets échangés dans une session d'admin avec la livebox on peut voir des réponses de POST en json . à‡a commence plutôt pas mal, la livebox a donc une API !
Comme souvent avec Orange, ça commence bien, c'est après que les choses se gâtent !
Impossible de mettre la main sur une doc publique de l'API. En fouillant un peu sur les forums d'Orange j'ai trouvé quelques pistes mais mes vrais amis ont été Wireshark et les dev tools InternetExplorer ou Chrome (F12) pour comprendre un peu comment l'appli mobile d'Orange (version IOS) utilisait l'API…
En inspectant le déroulé d'un login, je manque de m'étrangler en constatant que le nom d'utilisateur et le mot de passe sont balancés en clair; ben voyons les gars faut pas se gêner hein…
la requête login retourne un "ContextID" qui est utilisé comme identifiant pour les appels aux fonctions de l'API (X-Context dans les headers).
Donc au menu nous avons des custom headers et une authentification super basique, fastoche! où est le problème? Bah ça marche pô! - > "permission denied" le voilà le problème
Bah surement qu'ils ont été pris de remords chez Orange avec cette authentification de mickey avec password en clair et histoire de faire bonne figure (et pas se faire défoncer tous les mercredi par des pré-ados qui voudraient passer outre le contrôle parental) ils ont semble-t-il cherché à compliquer un peu les choses… mais en faisant du gros n'importe quoi! Pour aller à l'enssentiel, en plus d'un ContextID, le Login renvoie une autre clé mais planquée dans un cookie cette fois. La sécurité n'y a pas gagné grand chose mais en revanche c'est une vraie prise de tête à intégrer sur la hc2. Hmm.. Net.FHttp avec des custom headers et un cookie, ça va pas le faire…
Pour contourner le problème et récupérer le cookie, je me suis servi du génialissime ToolKit v1.0.4 de Krikroff.
Une toute petite modif de 4 lignes dans httpClient:request et nous voila prêts à nous goinfrer de cookies.
J'ai modifié (à l'arrache, sorry Krikroff) la fonction request(...) dans le fichier Toolkit.net.lua (commence ligne 165).
on cherche la chaine "cookie" dans les response headers renvoyés par le serveur et le cas échéant on extrait avec un string.sub() en partant du douzième char. la fonction retourne le cookie en plus des classiques response, status et err.
request = (function(self, method, uri, headers, body)
...
for k, v in pairs(__headers) do
--Toolkit.Net.__trace("raw #"..k..":"..v)
if (string.find(string.lower( v or ""), "chunked")) then
self.__isChunked = true;
Toolkit.Net.__trace("%s.%s::receive > Transfer-Encoding: chunked",
Toolkit.Net.__header, Toolkit.Net.__Http.__header, string.len(result));
-- Modification pour récupérer le cookie. Ofwood Janvier 2015
elseif (string.find(string.lower( v or ""), "cookie")) then
cookie = string.sub(v, 12)
Toolkit.Net.__trace("%s.%s::receive > Cookie: %s",
Toolkit.Net.__header, Toolkit.Net.__Http.__header, cookie);
end
end
...
-- return budy response & cookie
return response, status, err, cookie;
Voyons maintenant avec un exemple comment tirer profit de cette modification et mangeons des cookies!
La fonction login() authentifie l'utilisateur et retourne le contextID (dans la réponse json) et le cookie associé.
function login()
local httpClient = Toolkit.Net.HttpRequest(ip, port)
httpClient:setReadTimeout(Livebox.commandTimeOut)
local uri = string.format("/authenticate?username=%s&password=%s", utilisateur, mot_de_passe)
local response, status, errorCode, cookie = httpClient:request("POST", uri,
{"User-Agent: FibaroHC2/1.0", "Content-Type: application/json"}, "" )
if (errorCode == 0) and tonumber(status) == 200 then
local jsonTable = json.decode(response);
ContextID = jsonTable.data.contextID;
return ContextID, cookie
end
end
l'exemple suivant utilise le contextID et notre cookie pour une requête (l'état de l'interface WAN sur la LiveBox)
function getWANStatus(contextID, cookie)
local httpClient = Toolkit.Net.HttpRequest(ip, port)
httpClient:setReadTimeout(Livebox.commandTimeOut)
local uri = "/sysbus/NMC:getWANStatus"
local params = [[
{"parameters":{}}
]];
-- Injection de X-Context et du Cookie dans les headers
local response, status, errorCode, cookie = httpClient:request("POST", uri,
{"User-Agent: FibaroHC2/1.0",
"Content-Type: application/json",
"X-Context: "..contextID,
"Cookie: "..cookie },
params);
if (errorCode == 0) and (status == 200) then
local jsonTable = json.decode(response)
Return jsonTable.result.data
end
end
Voici la liste des fonctions implémentées dans la version 1.0 du module. Il en existe d'autres, je n'ai pas encore tout recensé.
Livebox.login() Authentification session utilisateur
Livebox.logout() Fermeture session
Livebox.listTrunks() Information téléphonie IP
Livebox.getIPTVStatus() Etat IP TV
Livebox.getDSLStats() Stats DSL (Erreurs)
Livebox.getMIBs() Information lien dsl
Livebox.getWifiMIBs() Information Wifi
Livebox.getWANStatus() Etat de la connexion WAN
Livebox.reboot() Redémarrage la livebox
Livebox.setwifi(mode) Active/désactive le Wifi
Livebox.filtreMAC(flag) Active/Désactive filtrage MAC address
Livebox.getWificomStatus() Information Wifi public Orange
Voilà , ça donne l'idée générale et Orange n'ayant pas le monopole sur les APIs bien pourries, je me suis dit que ça pourrait peut-être en aider d'autres qui se prennent la tête sur des intégrations nécessitant le support des cookies.
Enjoy!
merci pour vos retours (et votre indulgence)
Historique
13/01/2015 - v1.0 : version initiale
Livebox_VD.zip
Bonjour
Pour mon premier tuto, je vous propose un Module Virtuel pour interfacer la Livebox d'Orange et je vais vous détailler la mise en Å“uvre de l'intégration avec la HC2.
Le module rassemble les informations importantes sur l'état des interfaces, le débit, les statistiques et les différents compteurs d'erreurs. Il permet aussi d'exécuter des commandes simples comme l'activation du Wifi ou le redémarrage de la Livebox.
Prérequis
Une Livebox 2 (Sagem) DSL note: pas pu tester la fibre. J'aimerais bien mais dans moin coin c'est pas avant 2022 ). Une HC2 (code lua testé avec v3.600 et v4.031)
Installation
Télécharger et ajouter le VD (lien en bas de post)
Sur la page de configuration du module, saisir l'adresse ip et le port (80) de la Livebox
Ensuite, il faut paramtètrer le VD, editez le code en debut de page (pour chaque bouttons):
-- Nom d'utilisateur et mot de passe de la livebox
local USER ="admin"
local PASSWORD = "admin"
Le VD retourne trois états possibles: Inconnu, OK et Not OK. Editez les variables pour adapter l'ID des icones:
-- ID des icônes
icon_ok = 1004
icon_nok = 1005
icon_unknown = 1006
Par défault, l'execution du module toutes les 5 minutes est confié à la mainloop du VD qui simule un appui sur le bouton Rafraichir. Simple, mais pour plus de fléxibilité et surtout de plus stabilté je recommande d'utiliser l'excellent GEA avec la ligne ci-dessous (à adapter). Dans ce cas, noubliez pas de supprimer le code dans le mainloop du VD.
-- Mise à jour état connexion Internet
GEA.add(true , 5*60, "",{{"VirtualDevice", id["VD_LIVEBOX"], "1"},{"VirtualDevice", id["VD_LIVEBOX"], "7"},{"Repeat"}})
Le VD n'utilise pas de Variable Globale car je n'ai pas de scénario qui necessite un retour sur l'état de la connexion internet mais c'est juste une ligne de code à ajouter:
fibaro:setGlobal('test', Livebox.WANStatus.LinkState)
Comment ca marche ?
c'est la section pour les geeks. Je partage ici le resultat de mes bidouilles (et saut d'humeur) à propos de l'API Livebox
Fonctionnement de l'API Orange/Sagem:
En regardant d'un peu plus près les paquets échangés dans une session d'admin avec la livebox on peut voir des réponses de POST en json . à‡a commence plutôt pas mal, la livebox a donc une API !
Comme souvent avec Orange, ça commence bien, c'est après que les choses se gâtent !
Impossible de mettre la main sur une doc publique de l'API. En fouillant un peu sur les forums d'Orange j'ai trouvé quelques pistes mais mes vrais amis ont été Wireshark et les dev tools InternetExplorer ou Chrome (F12) pour comprendre un peu comment l'appli mobile d'Orange (version IOS) utilisait l'API…
En inspectant le déroulé d'un login, je manque de m'étrangler en constatant que le nom d'utilisateur et le mot de passe sont balancés en clair; ben voyons les gars faut pas se gêner hein…
la requête login retourne un "ContextID" qui est utilisé comme identifiant pour les appels aux fonctions de l'API (X-Context dans les headers).
Donc au menu nous avons des custom headers et une authentification super basique, fastoche! où est le problème? Bah ça marche pô! - > "permission denied" le voilà le problème
Bah surement qu'ils ont été pris de remords chez Orange avec cette authentification de mickey avec password en clair et histoire de faire bonne figure (et pas se faire défoncer tous les mercredi par des pré-ados qui voudraient passer outre le contrôle parental) ils ont semble-t-il cherché à compliquer un peu les choses… mais en faisant du gros n'importe quoi! Pour aller à l'enssentiel, en plus d'un ContextID, le Login renvoie une autre clé mais planquée dans un cookie cette fois. La sécurité n'y a pas gagné grand chose mais en revanche c'est une vraie prise de tête à intégrer sur la hc2. Hmm.. Net.FHttp avec des custom headers et un cookie, ça va pas le faire…
Pour contourner le problème et récupérer le cookie, je me suis servi du génialissime ToolKit v1.0.4 de Krikroff.
Une toute petite modif de 4 lignes dans httpClient:request et nous voila prêts à nous goinfrer de cookies.
J'ai modifié (à l'arrache, sorry Krikroff) la fonction request(...) dans le fichier Toolkit.net.lua (commence ligne 165).
on cherche la chaine "cookie" dans les response headers renvoyés par le serveur et le cas échéant on extrait avec un string.sub() en partant du douzième char. la fonction retourne le cookie en plus des classiques response, status et err.
request = (function(self, method, uri, headers, body)
...
for k, v in pairs(__headers) do
--Toolkit.Net.__trace("raw #"..k..":"..v)
if (string.find(string.lower( v or ""), "chunked")) then
self.__isChunked = true;
Toolkit.Net.__trace("%s.%s::receive > Transfer-Encoding: chunked",
Toolkit.Net.__header, Toolkit.Net.__Http.__header, string.len(result));
-- Modification pour récupérer le cookie. Ofwood Janvier 2015
elseif (string.find(string.lower( v or ""), "cookie")) then
cookie = string.sub(v, 12)
Toolkit.Net.__trace("%s.%s::receive > Cookie: %s",
Toolkit.Net.__header, Toolkit.Net.__Http.__header, cookie);
end
end
...
-- return budy response & cookie
return response, status, err, cookie;
Voyons maintenant avec un exemple comment tirer profit de cette modification et mangeons des cookies!
La fonction login() authentifie l'utilisateur et retourne le contextID (dans la réponse json) et le cookie associé.
function login()
local httpClient = Toolkit.Net.HttpRequest(ip, port)
httpClient:setReadTimeout(Livebox.commandTimeOut)
local uri = string.format("/authenticate?username=%s&password=%s", utilisateur, mot_de_passe)
local response, status, errorCode, cookie = httpClient:request("POST", uri,
{"User-Agent: FibaroHC2/1.0", "Content-Type: application/json"}, "" )
if (errorCode == 0) and tonumber(status) == 200 then
local jsonTable = json.decode(response);
ContextID = jsonTable.data.contextID;
return ContextID, cookie
end
end
l'exemple suivant utilise le contextID et notre cookie pour une requête (l'état de l'interface WAN sur la LiveBox)
function getWANStatus(contextID, cookie)
local httpClient = Toolkit.Net.HttpRequest(ip, port)
httpClient:setReadTimeout(Livebox.commandTimeOut)
local uri = "/sysbus/NMC:getWANStatus"
local params = [[
{"parameters":{}}
]];
-- Injection de X-Context et du Cookie dans les headers
local response, status, errorCode, cookie = httpClient:request("POST", uri,
{"User-Agent: FibaroHC2/1.0",
"Content-Type: application/json",
"X-Context: "..contextID,
"Cookie: "..cookie },
params);
if (errorCode == 0) and (status == 200) then
local jsonTable = json.decode(response)
Return jsonTable.result.data
end
end
Voici la liste des fonctions implémentées dans la version 1.0 du module. Il en existe d'autres, je n'ai pas encore tout recensé.
Livebox.login() Authentification session utilisateur
Livebox.logout() Fermeture session
Livebox.listTrunks() Information téléphonie IP
Livebox.getIPTVStatus() Etat IP TV
Livebox.getDSLStats() Stats DSL (Erreurs)
Livebox.getMIBs() Information lien dsl
Livebox.getWifiMIBs() Information Wifi
Livebox.getWANStatus() Etat de la connexion WAN
Livebox.reboot() Redémarrage la livebox
Livebox.setwifi(mode) Active/désactive le Wifi
Livebox.filtreMAC(flag) Active/Désactive filtrage MAC address
Livebox.getWificomStatus() Information Wifi public Orange
Voilà , ça donne l'idée générale et Orange n'ayant pas le monopole sur les APIs bien pourries, je me suis dit que ça pourrait peut-être en aider d'autres qui se prennent la tête sur des intégrations nécessitant le support des cookies.
Enjoy!
merci pour vos retours (et votre indulgence)
Historique
13/01/2015 - v1.0 : version initiale
Livebox_VD.zip