[Tuto] Freebox
Publié : 22 mars 2018, 00:32
Hello.
J'ai commencé a adapter un script que papoo avait ramené ici.
J'ai juste nettoyer un peu et creer trois fonctions:
getOnFreebox(api)
putOnFreebox(api,data)
postOnFreebox(api)
Qui permette respectivement de récupérer des données dans une table en envoyant l'api du site, de charger une table avec l'api du site, et de demander une modification avec l'api du site.
https://dev.freebox.fr/sdk/os/
J'ai aussi réduit un peu une des fonction qui était présente:
getPeripheriquesConnectes() Elle permet de passer une adresse mac en argument et d'activer un switch si l’équipement est connecté.
J'ai aussi créer une fonction pour activer ou non l'ouverture d'un port (NAT ou Portforwarding):
portForwarding() Je souhaitais me servir de ça pour empêcher une connexion extérieur à domoticz. Mais l'autoriser seulement si je suis a hors de la maison. (Si getPeripheriquesConnectes() retourne false portForwarding() envoi true).
Si jamais ca peut interresser, ou si quelqu'un veut aller plus loin ce sera interressant.
[EDIT] Il ne devrait normalement pas avoir besoin de configuration. Le script va verifier que vous avez le droit de vous connecter a la freebox en cherchant une variable utilisateur. Si elle n'existe pas, il l'a créé et fait une demande a la freebox. Vous devez accepter cette demande sur l'ecran de la freebox. Il stock ensuite l'autorisation dans cette variable pour la recuperer a chaque connexion.
Vous pouvez mettre le script en time ou a l'activation d'un device ou autre... Si il n'a jamais ete lancé, alors vous devez au minimum le lancer une fois avant utilisation pour accepter l'autorisation de connexion a la freebox.
Voici le script:
J’espère qu'on pourra en discuter pour l’agrémenter.
J'ai commencé a adapter un script que papoo avait ramené ici.
J'ai juste nettoyer un peu et creer trois fonctions:
getOnFreebox(api)
putOnFreebox(api,data)
postOnFreebox(api)
Qui permette respectivement de récupérer des données dans une table en envoyant l'api du site, de charger une table avec l'api du site, et de demander une modification avec l'api du site.
https://dev.freebox.fr/sdk/os/
J'ai aussi réduit un peu une des fonction qui était présente:
getPeripheriquesConnectes() Elle permet de passer une adresse mac en argument et d'activer un switch si l’équipement est connecté.
J'ai aussi créer une fonction pour activer ou non l'ouverture d'un port (NAT ou Portforwarding):
portForwarding() Je souhaitais me servir de ça pour empêcher une connexion extérieur à domoticz. Mais l'autoriser seulement si je suis a hors de la maison. (Si getPeripheriquesConnectes() retourne false portForwarding() envoi true).
Si jamais ca peut interresser, ou si quelqu'un veut aller plus loin ce sera interressant.
[EDIT] Il ne devrait normalement pas avoir besoin de configuration. Le script va verifier que vous avez le droit de vous connecter a la freebox en cherchant une variable utilisateur. Si elle n'existe pas, il l'a créé et fait une demande a la freebox. Vous devez accepter cette demande sur l'ecran de la freebox. Il stock ensuite l'autorisation dans cette variable pour la recuperer a chaque connexion.
Vous pouvez mettre le script en time ou a l'activation d'un device ou autre... Si il n'a jamais ete lancé, alors vous devez au minimum le lancer une fois avant utilisation pour accepter l'autorisation de connexion a la freebox.
Voici le script:
Code : Tout sélectionner
script = ' [Freebox] ' ; commandArray={}
------------------------------------------- Condition d'ouverture ----------------------------------------------
------------------------------------------ Declaration de fonction ---------------------------------------------
debug = 1 -- LOG: nil ou 0:LOG, 1:INFO, 2:DEBUG, 3:ERROR
log('----------------------------------------------------------------------------------------------------------------------',1)
--################################################################################################################################--
--################################################################################################################################--
--################## Declaration des variables ##################--
--################################################################################################################################--
-- Declaration des parametres FREEBOX
local FreeboxAPPID = "Domoticz.Freebox.app"
local FreeboxURL = "http://mafreebox.freebox.fr"
-- Declaration des variables
local FreeboxAPI = ""
local FreeboxSESSIONTOKEN = ""
--################################################################################################################################--
--################## Declaration des fonction de base ##################--
--################################################################################################################################--
function io.capture(cmd, raw)
local file = assert(io.popen(cmd, 'r'))
local result = assert(file:read('*a'))
file:close()
if raw then return result end
result = string.gsub(result, '^%s+', '')
result = string.gsub(result, '%s+$', '')
result = string.gsub(result, '[\n\r]+', ' ')
return result
end
function log(txt,lvl)
if lvl==nil or lvl==0 then
print("<font color='green'>" .. script .. '#LOG: ' .. txt .. "</font>")
elseif lvl>=3 then
error(script .. ' ' .. txt)
else
if lvl<=debug then
if lvl==1 then
print("<font color='yellow'>" .. script .. '#INFO: ' .. txt .. "</font>")
elseif lvl==2 then
print("<font color='red'>" .. script .. '#DEBUG: ' .. txt .. "</font>")
end
end
end
end
--################################################################################################################################--
--################## Fonction de connexion Freebox ##################--
--################################################################################################################################--
--Fonction de recuperation (Test) de l'API Freebox
--Permet de verifier la presence et l'acces à l'api de la freebox
--Arguments: URL: FreeboxURL.
--Resultats: baseAPI: url+api de base.
function FreeboxBaseAPI()
log("FreeboxBaseAPI",2)
local command = 'curl -s -H "Content-Type: application/json" -X GET ' .. FreeboxURL .. '/api_version'
local output = json:decode(io.capture(command))
log(command..'\n'..json:encode_pretty(output),2)
local FreeboxBaseAPI = output.api_base_url..'v'..math.floor(tonumber(output.api_version))
log("FreeboxBaseAPI: OK",1)
return FreeboxBaseAPI
end
local FreeboxBaseAPI = FreeboxBaseAPI()
function FreeboxAppTokenRequestTrack(app_token,track_id)
log("FreeboxAppTokenRequestTrack",2)
local command = 'curl -s -H "Content-Type: application/json" -X GET ' .. FreeboxURL .. FreeboxBaseAPI .. '/login/authorize/'..track_id
local output = json:decode(io.capture(command))
log(command..'\n'..json:encode_pretty(output),2)
log("FreeboxAppTokenRequestTrack: OK",1)
local status = output.result.status
if output.success then
local FreeboxAPPToken = 'app_token:'..app_token..';track_id:'..track_id..";status:"..output.result.status
local url = 'curl "http://'..os.execute('hostname')..'/json.htm?type=command¶m=updateuservariable&vname=FreeboxAPPToken&vtype=2&vvalue='..url_encode(FreeboxAPPToken)..'" &'
os.execute(url)
log(FreeboxAPPToken,1)
if status=='granted' then
return app_token
elseif status=='pending' then
error("L'administrateur doit autoriser la demande d'authentification sur l'ecran de la Freebox")
elseif status=='timeout' then
--local url = 'curl "http://'..os.execute('hostname')..'/json.htm?type=command¶m=updateuservariable&vname=FreeboxAPPToken&vtype=2&vvalue=timeout" &'
--os.execute(url)
error("L'administrateur n'a pas autorisé l'authentification à temps. Veuillez supprimer le FreeboxAPPToken et recommencer")
elseif status=='unknown' then
--local url = 'curl "http://'..os.execute('hostname')..'/json.htm?type=command¶m=updateuservariable&vname=FreeboxAPPToken&vtype=2&vvalue=unknown" &'
--os.execute(url)
error("L'app token est invalide ou a été révoqué")
elseif status=='denied' then
--local url = 'curl "http://'..os.execute('hostname')..'/json.htm?type=command¶m=updateuservariable&vname=FreeboxAPPToken&vtype=2&vvalue=denied" &'
--os.execute(url)
error("L'administrateur a refusé votre accés à la Freebox")
else
error('Autre erreur.')
end
else
log('FreeboxAppTokenRequestTrack Erreur'..output.error_code..' - '..output.msg)
end
end
function FreeboxAppTokenRequest()
local auth = {}
auth["app_id"]=FreeboxAPPID
auth["app_name"]="Domoticz"
auth["app_version"]="0.1"
auth["device_name"]=io.capture('hostname')
local jsonAuth = json:encode_pretty(auth)
log("FreeboxAppTokenRequest",2)
local command = 'curl -s -H "Content-Type: application/json" -X POST -d \'' .. jsonAuth .. '\' ' .. FreeboxURL .. FreeboxBaseAPI .. '/login/authorize/'
local output = json:decode(io.capture(command))
log(command..'\n'..json:encode_pretty(output),2)
local app_token = output.result.app_token
local track_id = output.result.track_id
log("FreeboxAppTokenRequest: OK",1)
FreeboxAppTokenRequestTrack(app_token,track_id)
end
--Authentification pour récupérer le Token De Session-------------------------------------------------------------------------------
--Variable: FreeboxURL; FreeboxAPPTOKEN; FreeboxAPPID
--Retourne: FreeboxSessionToken
function FreeboxConnect()
log("Connexion à la Freebox")
local FreeboxAPPToken = FreeboxAPPToken()
--Recuperation du Challenge
log("Recuperation du challenge",2)
local url = 'curl -s ' .. FreeboxAPI .. '/login'
local output = json:decode(io.capture(url, false))
log("Challenge : " .. output.result.challenge,2)
local FreeboxCHALLENGE = output.result.challenge
--Hashage en sha1 du Mot De Passe via l'os
log("Calcul du mot de passe",2)
local url = 'echo -n ' .. FreeboxCHALLENGE .. ' | openssl dgst -sha1 -hmac ' .. FreeboxAPPToken .. ' | cut -c10-200 '
local output = io.capture(url, false)
log("Password : " .. output,2)
local FreeboxPWD = output:gsub("\n", "")
--Recuperation d'un Token avec FreeboxPWD + FreeboxAPPID
local session = {}
session["app_id"]=FreeboxAPPID
session["password"]=FreeboxPWD
local jsonSession = json:encode_pretty(session)
--Connexion à la session
log("Recuperation du token de session",2)
local command = 'curl -s -H "Content-Type: application/json" -X POST -d \'' .. jsonSession .. '\' ' .. FreeboxURL .. FreeboxBaseAPI .. '/login/session/'
local output = json:decode(io.capture(command, false))
log("Session Token : " .. output.result.session_token,1)
FreeboxSessionToken = output.result.session_token
end
--Fonction de deconnexion de la Freebox-------------------------------------------------------------------------------------------
--Variable: FreeboxSessionToken; FreeboxAPI
--retour table: output
function FreeboxDisconnect()
local command = 'curl -s -H "Content-Type: application/json" -H "X-Fbx-App-Auth: ' .. FreeboxSessionToken .. '" -X POST '..FreeboxURL .. FreeboxBaseAPI .. '/login/logout'
local output = json:decode(io.capture(command, false))
log('Deconnexion: '..tostring(output.success),1)
end
----------------------------------------------------------------------------------------------------------------------
function FreeboxAPPToken()
if uservariables['FreeboxAPPToken']==nil then
local url = 'curl "http://'..os.execute('hostname')..'/json.htm?type=command¶m=saveuservariable&vname=FreeboxAPPToken&vtype=2&vvalue=" &'
os.execute(url)
end
local FreeboxAPPToken=uservariables['FreeboxAPPToken']
if FreeboxAPPToken:find('status') then
log('test')
local key = 'status'
local status = FreeboxAPPToken:match(key..':([^;]+)')
local key = 'app_token'
local app_token = FreeboxAPPToken:match(key..':([^;]+)')
local key = 'track_id'
local track_id = FreeboxAPPToken:match(key..':([^;]+)')
log('app_token:'..app_token..';track_id:'..track_id..";status:"..status,1)
if status=='granted' then
return app_token
else
FreeboxAppTokenRequestTrack(app_token,track_id)
end
else
FreeboxAppTokenRequest()
end
end
--################################################################################################################################--
--################## Fonction de controle Freebox ##################--
--################################################################################################################################--
--Fonction de recuperation de parametre freebox-----------------------------------------------------------------------------------------
--Parametre:
--api (string) correspond à l'api du site 'https://dev.freebox.fr/sdk/os/#api-list' ex:
-- '/api/v4/fw/redir/' (Recupere la liste du routage de port 'NAT')
--Variable: FreeboxSessionToken; FreeboxURL
--retour table: output
function getOnFreebox(api)
local url = 'curl -s -H "Content-Type: application/json" -H "X-Fbx-App-Auth: ' .. FreeboxSessionToken .. '" -X GET ' .. FreeboxURL .. api
local output = json:decode(io.capture(url, false))
log('Recuperation de données freebox',1)
log('URL: '..url..'\nRetour:\n'..json:encode_pretty(output),2)
return output
end
--Fonction de modification de parametre freebox-----------------------------------------------------------------------------------------
--Parametre:
--api (string) correspond à l'api du site 'https://dev.freebox.fr/sdk/os/#api-list' ex:
-- '/api/v4/fw/redir/1' (Modifie le port avec ID=1)
--data (table) correspond au parametre a passer dans l'api ex:
-- data={"enabled": false} (desactive le routage de port)
--Variable: FreeboxSessionToken; FreeboxURL
--retour table: output
function putOnFreebox(api,data)
local data = json:encode_pretty(data)
local url = 'curl -s -H "Content-Type: application/json" -H "X-Fbx-App-Auth: ' .. FreeboxSessionToken .. '" -X PUT -d \'' .. data .. '\' '.. FreeboxURL .. api
local output = json:decode(io.capture(url, false))
log('Insertion de données freebox',1)
log('URL: '..url..'\nDonnées insérées: \n'..json:encode_pretty(data)..'\nRetour:\n'..json:encode_pretty(output),2)
return output
end
--Fonction POST parametre freebox-----------------------------------------------------------------------------------------
--Parametre:
--api (string) correspond à l'api du site 'https://dev.freebox.fr/sdk/os/#api-list' ex:
-- /api/v4/system/reboot/' (Reboot la freebox)
--Variable: FreeboxSESSIONTOKEN; FreeboxURL
--retour table: output
function postOnFreebox(api)
local data = json:encode_pretty(data)
local url = 'curl -s -H "Content-Type: application/json" -H "X-Fbx-App-Auth: ' .. FreeboxSessionToken .. '" -X POST '.. FreeboxURL .. api
local output = json:decode(io.capture(url, false))
log('Insertion de données freebox',1)
log('URL: '..url..'\nRetour:\n'..json:encode_pretty(output),2)
return output
end
--################################################################################################################################--
--################## Fonction spécifique ##################--
--################################################################################################################################--
-- Fonction de recherche de périphérique connecté
-- Connexion à lan/browser/pub/ recuperer l'etat de connexion d'une adresse mac
-- parametre table: user (user et mac adresse)
-- retour aucun; Activation d'un device propre à l'user
function getPeripheriquesConnectes(user)
for user,device in pairs(user) do
result = getOnFreebox('/api/v4/lan/browser/pub/ether-' .. device)
if not otherdevices['Smartphone'..user] then
--creation du device
error('Device Smartphone '..user..': Non créé')
end
if result.l3connectivities.reachable then
if otherdevices['Smartphone'..user]=='Off' then
commandArray['Smartphone'..user]='On'
end
else
if otherdevices['Smartphone'..user]=='On' then
commandArray['Smartphone'..user]='Off'
end
end
end
end
-- Fonction d'activation d'un routage de port (NAT)
-- parametre: id correspond a l'id de la regle; true ou false pour activer ou desactiver la regle
-- retour booleen: true ou false si succes
function portForwarding(id,enabled)
log('Port Forwarding Ecriture',1)
local data = {}
data["enabled"]=enabled
local data = json:encode_pretty(data)
result = putOnFreebox('/api/v4/fw/redir/' .. id,data)
return result.success
end
--################################################################################################################################--
--################## Boucle principale ##################--
--################################################################################################################################--
local init = false
if init then
FreeboxConnect() -- obligatoire
api='/api/v4/system/'
system=getOnFreebox(api)
log('Uptime: '..system.result.uptime..' Version: '..system.result.firmware_version)
user={}
user["Benjamin"]="FF:FF:FF:FF:FF";
user["Celine"]="AA:AA:AA:AA:AA"
getPeripheriquesConnectes(user)
--Recuperer la totalité des equipements connectés
--api='/api/v4/lan/browser/pub'
--getOnFreebox(api)
--portForwarding(1,false)
FreeboxDisconnect() -- obligatoire
end
log('----------------------------------------------------------------------------------------------------------------------',1) ; return commandArray