Message populaire Nikko Posté(e) le 14 juillet 2016 Message populaire Signaler Posté(e) le 14 juillet 2016 Bonjour, Voici un résumé sur la réalisation/suppression de backups via des scènes en Lua. La création/suppression de backup s'effectue en temps normal sur l'interface du HomeCenter à la page Diagnostiques/Sauvegarde et restauration. Le code donné dons les 2 scènes n'est pas des plus optimisé; cela constitue juste une base. EDIT (03/12/2016): Mise à jour avec l'api pour les versions >=4.101; voir plus loin: (https://www.domotique-fibaro.fr/topic/8641-backup-via-scene-lua/?do=findComment&comment=146362) Les Commandes de l'API La récupération au format JSON de la liste des backups se fait à l'addresse http://HC2/api/settings/backups Pour Créer un Backup on utilise l'addresse http://HC2/api/settings/backups avec une requète de type en POST avec les paramètres action et description. Pour Supprimer un Backup, on utilise l'addresse http://HC2/api/settings/backups?id=xx (où xx est le numéro de backup). La requète est de type DELETE avec comme paramètre id=xx => Comme les urls de l'api vont être appelées depuis des scènes lua, l'ip de la box utilisée sera 127.0.0.1 (port 11111) => En cas d'appel sur l'ip LAN de la box (Ex: http://192.168.0.100/api/settings/backups) , il faudra en plus transmettre l'authentification dans la requète. Attention: Lors de la création de Backup, "tout le reste" est suspendu; de même après que le backup soit effectué, le moteur Z-Wave et d'autres services redémarrent. Donc en cas de planification , privilégier la nuit, là ou l'activité ZWave, scénarios, est faible/inexistante. Scène de création d'un backup Exemple de Scène de création d'un Backup, avec notification vers portable: --[[ %% properties %% events %% globals --]] -- ID des mobiles,tablettes pour notification local portable = { 385,378 } -- Message Descriptif du Backup local descriptif = 'Backup du '..os.date("%d/%m/%y - %HH%M") function sendPush(message) if #portable > 0 then for _,v in ipairs(portable) do fibaro:call(v,'sendPush', message) end end end local url = 'http://127.0.0.1:11111/api/settings/backups' local httpClient = net.HTTPClient() httpClient:request(url , { success = function(response) if tonumber(response.status) == 201 then print("Backup Created at " .. os.date()) sendPush(descriptif .. ' effectué') else print("Error " .. response.status) sendPush('Erreur lors de la création du Backup') end end, error = function(err) print('error = ' .. err) end, options = { method = 'POST', headers = { ["content-type"] = 'application/x-www-form-urlencoded;' }, data = 'action=create&description='..descriptif } }); Depuis la page des backups, on peut vérifier que la scène fonctionne: Pour les utilisateurs de GEA, on peut déclencher cette sauvegarde le 1er samedi de chaque mois par exemple: -- Fonction déterminant si nous sommes le 1er samedi du mois function isFirstSaturday() local t = os.date('*t') return ( t['day'] < 8 and t['wday'] == 7 ) end -- Backup le 1er samedi du mois GEA.add({"Function",function() return isFirstSaturday() end} , 30 , "Backup Mensuel du HC2" , {{"Time","01:00","01:01"},{"Scenario", 12}}) . Scène de suppression d'un backup Exemple de Scene Lua pour réaliser la suppression du backup le plus ancien: --[[ %% properties %% events %% globals --]] -- Flag dryrun; Si true, la requete sur api pour effacer le backup n'est pas effectuée local dryrun = true -- Récupération de la list des backups local backups = api.get('/settings/backups') -- Vérification de présence Backup if (backups and type(backups == 'table') and #backups > 0) then if #backups > 1 then print(#backups .. ' Backups présents') else print('1 Backup présent') end for i in ipairs(backups) do fibaro:debug('ID: '..backups[i]['id']..' | TIMESTAMP: '..backups[i]['timestamp']..' | DESCRIPTION: '..backups[i]['description']) end else print('Pas de backup ou erreur lors de la récupération de la liste') fibaro:abort() end -- Pour chaque Backup on stock le timestamp de la date de réalisation dans une table -- On classe ensuite les timestamps par ordre croissant local timestamp = {} for i in ipairs(backups) do table.insert(timestamp, backups[i]['timestamp']) end table.sort(timestamp) -- Le 1er timestamp de la table est le plus petit donc le plus ancien en epochtime -- Dans la table de backup on recherche le backup ayant ce timestamp local id = false for i in ipairs(backups) do if (tonumber(backups[i]['timestamp']) == tonumber(timestamp[1])) then id = backups[i]['id'] end end if id then print("ID du backup le plus ancien: "..id) else print("Erreur lors de la récupération de l'ID") fibaro:abort() end -- Requete via API pour effacer le backup le plus ancien if not dryrun then local url = 'http://127.0.0.1:11111/api/settings/backups?id='..id local httpClient = net.HTTPClient() httpClient:request(url , { success = function(response) if tonumber(response.status) == 200 then print("Backup deleted at " .. os.date()) else print("Error " .. response.status) end end, error = function(err) print('error = ' .. err) end, options = { method = 'DELETE', headers = { ["content-type"] = 'application/x-www-form-urlencoded;' }, data = 'id='..id } }); end . Cette Scène produit le debug suivant: Nicolas 12
Sakkhho Posté(e) le 14 juillet 2016 Signaler Posté(e) le 14 juillet 2016 merci, bien pratique effectivement je mets en place mais je vais faire des backup hebdo, jamais assez prudent avec la HC2 -- Backup Auto HC2 GEA.add(true, 30, "Backup Hebdo HC2" , {{"Days", "Thursday"},{"Time","12:10","12:11"},{"Scenario", 312}}) GEA.add(true, 30, "Delete Bakcup HC2", {{"Days", "Thursday"},{"Time","12:05","12:05"},{"Scenario", 313}}) Du coup, il faut mettre la scene en 'MANUELLE" ? avec la nouvelle option de la HC2
Sakkhho Posté(e) le 14 juillet 2016 Signaler Posté(e) le 14 juillet 2016 Alors le backup auto fonctionne bien mais le Delete non j'ai ca dans le log il n'execute pas la DELETE. [DEBUG] 13:11:33: 13 Backups présents [DEBUG] 13:11:33: ID: 452 | TIMESTAMP: 1468491024 | DESCRIPTION: Backup du 14/07/16 - 12H10 [DEBUG] 13:11:33: ID: 451 | TIMESTAMP: 1468411713 | DESCRIPTION: Stable [DEBUG] 13:11:33: ID: 449 | TIMESTAMP: 1468166875 | DESCRIPTION: Stable 4.090 [DEBUG] 13:11:33: ID: 448 | TIMESTAMP: 1468161140 | DESCRIPTION: 4.083->4.090 [DEBUG] 13:11:33: ID: 445 | TIMESTAMP: 1467471985 | DESCRIPTION: 4.080->4.083 [DEBUG] 13:11:33: ID: 450 | TIMESTAMP: 1465737177 | DESCRIPTION: Stable [DEBUG] 13:11:33: ID: 447 | TIMESTAMP: 1457115357 | DESCRIPTION: 4.070->4.080 [DEBUG] 13:11:33: ID: 457 | TIMESTAMP: 1454093563 | DESCRIPTION: 4.056->4.070 [DEBUG] 13:11:33: ID: 446 | TIMESTAMP: 1451844568 | DESCRIPTION: V2015 Optimisée [DEBUG] 13:11:33: ID: 453 | TIMESTAMP: 1440080155 | DESCRIPTION: 4.049->4.056 [DEBUG] 13:11:33: ID: 455 | TIMESTAMP: 1429877186 | DESCRIPTION: 4.040->4.042 [DEBUG] 13:11:33: ID: 456 | TIMESTAMP: 1427395206 | DESCRIPTION: 4.036->4.040 [DEBUG] 13:11:33: ID: 454 | TIMESTAMP: 1424505690 | DESCRIPTION: 3.600->4.033 [DEBUG] 13:11:33: ID du backup le plus ancien: 454 en prime des icônes pour les scenes
Nikko Posté(e) le 14 juillet 2016 Auteur Signaler Posté(e) le 14 juillet 2016 Salut, Le code fonctionne chez moi, mais comme je n'ai pas pu l'utiliser chez plusieurs personnes, j'ai mis une "sécurite": la variable dryrun. Si sur true le delete n'est pas executé si sur false le delete se fait. C'est justement pour vérifier que l'id retournée correspond bien au backup le plus ancien: ça évite de supprimer si erreur. as tu bein basculé le flag dans le script ?
Sakkhho Posté(e) le 14 juillet 2016 Signaler Posté(e) le 14 juillet 2016 désolé j'avais pas vu le flag c'est parfait c'est 2 scenes !
Lazer Posté(e) le 14 juillet 2016 Signaler Posté(e) le 14 juillet 2016 Perso c'est backup toutes les semaines, dans la nuit de samedi àdimanche. En plus, le backup ne démarre que si la Variable globale VACANCES = 0, afin de ne pas risque de rendre la box instable durant mon absence. On a déjàvu un simple backup faire planter le moteur Z-Wave.....
971jmd Posté(e) le 21 juillet 2016 Signaler Posté(e) le 21 juillet 2016 Salut @Niko penses-tu qu'il est possible de réaliser la sauvguard sur un serveur plutôt que sur la clé ?
Nikko Posté(e) le 21 juillet 2016 Auteur Signaler Posté(e) le 21 juillet 2016 @971jmd, L'api ou l'utilisation de l'interface fibaro ne permet pas de le faire. Il existe des possibilités en ayant l'accès root sur la box, mais je ne m'étendrai pas sur le sujet
971jmd Posté(e) le 21 juillet 2016 Signaler Posté(e) le 21 juillet 2016 Oui merci Envoyé de mon iPhone en utilisant Tapatalk
pepite Posté(e) le 24 juillet 2016 Signaler Posté(e) le 24 juillet 2016 SAlut @Nikko, j'avais a-pas vu..top Merci beaucoup, on en avait parlé et tu l'as fait !! c'est MEGA TOP ;-) merci vraiment. @971jmd, possible si on est root ;-) 1
cybersquat Posté(e) le 24 juillet 2016 Signaler Posté(e) le 24 juillet 2016 super intéressant, merci beaucoup, je met en place dès ce soir Merci !
pepite Posté(e) le 30 juillet 2016 Signaler Posté(e) le 30 juillet 2016 Un grand merci !! Mis en place Nickel comme toujours avec les experts !!! Au top
kioneoranga Posté(e) le 1 août 2016 Signaler Posté(e) le 1 août 2016 Super en place chez moi Je verrais comment cela fonctionne en auto via GEA samedi prochain (sic)
971jmd Posté(e) le 1 août 2016 Signaler Posté(e) le 1 août 2016 SAlut @Nikko, j'avais a-pas vu..top Merci beaucoup, on en avait parlé et tu l'as fait !! c'est MEGA TOP ;-) merci vraiment. @971jmd, possible si on est root ;-) Salut, Qu'appelle tu Root? Envoyé de mon iPhone en utilisant Tapatalk
Titof_44 Posté(e) le 30 novembre 2016 Signaler Posté(e) le 30 novembre 2016 l'API a du changer car cela ne marche plus depuis la V4.101. . 1
Lazer Posté(e) le 30 novembre 2016 Signaler Posté(e) le 30 novembre 2016 Oui, Nikko a donné la nouvelle API :
pepite Posté(e) le 30 novembre 2016 Signaler Posté(e) le 30 novembre 2016 Ah, @Lazer plus rapide ;-) API du backup : http://homecenter/api/service/backups
Nikko Posté(e) le 3 décembre 2016 Auteur Signaler Posté(e) le 3 décembre 2016 Bonjour Mise à jour: Suite au passage en 4.101 et plus, l'API a changé concernant les backups; voici donc un résumé en fonction des versions API pour Version < 4.101 BACKUP: URL: http://ip/api/settings/backups TYPE: POST DATA: action=create&description=monbackup HEADER: Content-type: application/x-www-form-urlencoded RESTORE: URL: http://ip/api/settings/backups TYPE: POST DATA: action=restore&id=1051 (par exemple) HEADER: Content-type: application/x-www-form-urlencoded DELETE: URL: http://ip/api/settings/backups?id=xxxx (xxx: id du backup) TYPE: DELETE DATA: id=xxxx HEADER: Content-type: application/x-www-form-urlencoded API pour Version >= 4.101 BACKUP: URL: http://ip/api/service/backups/ TYPE: POST DATA: {"action":"create","params":{"name":"Le descriptif de mon backup"}} HEADER: Content-type: application/x-www-form-urlencoded Authorization: Basic xxxxxxxxxxxxxxxx (mot de passe encodé en base64) RESTORE: URL: http://ip/api/service/backups/ TYPE: POST DATA: {"action":"restore","params":{"id":1054}} (1054 est un exemple) HEADER: Content-type: application/x-www-form-urlencoded Authorization: Basic xxxxxxxxxxxxxxxx (mot de passe encodé en base64) DELETE: URL: http://ip/api/service/backups/ TYPE: DELETE DATA: n/a HEADER: Authorization: Basic xxxxxxxxxxxxxxxx (mot de passe encodé en base64) Encodage Base64 Pour le couple login/password, ils doivent être encodés en base64; Pour ce faire: Sous linux: echo -n 'monlogin@fai.com:motdepasse' | base64 Sous windows: une scene en lua sur le HC2 : taper base64.lua sous google Le toolkit de @Krikroff (https://www.domotique-fibaro.fr/topic/239-hc2-toolkit-application-v1203/) Advanced RESTful client: faire une requete sur une url de l'api, le couple login/mdp sera demandé et sera affiché ensuite encodé. Exemple de Scènes Pour des requêtes externes, cela ne change pas vraiment. En revanche pour ceux qui comptent réaliser des scènes de backup/delete, ces requètes ne sont plus gérées pareil (avant en local, nous utilisions 127.0.0.1:11111 qui est géré par le process HCServer; maintenant il faut utiliser 127.0.0.1 et pointer sur un php) Donc pour les scènes lua, pas de api.post ou api.get et authentification nécessaire. Voici 2 scènes exemples; Les scène ne sont pas forcèment optimisées. Elles montrent juste l'utilisation de l'api Scène de Backup: performBackup.lua --[[ %% properties %% events %% globals --]] -- Message Descriptif du Backup local descriptif = 'Backup du '..os.date("%d/%m/%y - %HH%M") -- Password admin encodé en base64 local password = 'aWRpb3RAZ3Z1bGF2aWVyZ2UuY29tOnR1X3lfY3JveWFpc19oZWlu' local url = 'http://127.0.0.1/api/service/backups' local datas = '{"action":"create","params":{"name":"'..descriptif..'"}}' local httpClient = net.HTTPClient() httpClient:request(url , { success = function(response) if tonumber(response.status) == 201 or tonumber(response.status) == 202then print("Backup Created at " .. os.date()) else print("Error " .. response.status) end end, error = function(err) print('error = ' .. err) end, options = { method = 'POST', headers = { ["content-type"] = 'application/json', ["Authorization"] = 'Basic '..password }, data = datas } }); Scene d'effacement du backup le plus ancien: deleteBackup.lua --[[ %% properties %% events %% globals --]] -- Flag dryrun; Si true, la requete sur api pour effacer le backup n'est pas effectuée local dryrun = true -- Password admin encodé en base64 local password = 'aWRpb3RAZ3Z1bGF2aWVyZ2UuY29tOnR1X3lfY3JveWFpc19oZWlu' function sortBackup(data) local backups = json.decode(data) -- Vérification de présence Backup if (backups and type(backups == 'table') and #backups > 0) then if #backups > 1 then print(#backups .. ' Backups présents') else print('1 Backup présent') end for i in ipairs(backups) do fibaro:debug('ID: '..backups[i]['id']..' | TIMESTAMP: '..backups[i]['timestamp']..' | DESCRIPTION: '..backups[i]['description']) end else print('Pas de backup ou erreur lors de la récupération de la liste') fibaro:abort() end -- Pour chaque Backup on stock le timestamp de la date de réalisation dans une table -- On classe ensuite les timestamps par ordre croissant local timestamp = {} for i in ipairs(backups) do table.insert(timestamp, backups[i]['timestamp']) end table.sort(timestamp) -- Le 1er timestamp de la table est le plus petit donc le plus ancien en epochtime -- Dans la table de backup on recherche le backup ayant ce timestamp local id = false for i in ipairs(backups) do if (tonumber(backups[i]['timestamp']) == tonumber(timestamp[1])) then id = backups[i]['id'] end end if id then print("ID du backup le plus ancien: "..id) deleteBackup(id) else print("Erreur lors de la récupération de l'ID") fibaro:abort() end end function deleteBackup(id) -- Requete via API pour effacer le backup le plus ancien if (not dryrun) and (id) then print('Effacement du backup '..id..' en cours. Cela peut prendre 30s') local url = 'http://127.0.0.1/api/service/backups/'..id local httpClient = net.HTTPClient() httpClient:request(url , { success = function(response) if tonumber(response.status) == 200 then print("Backup deleted at " .. os.date()) else print("Error " .. response.status) end end, error = function(err) print('error = ' .. err) end, options = { method = 'DELETE', headers = { ["content-type"] = 'application/x-www-form-urlencoded;', ["authorization"] = 'Basic '..password }, data = 'id='..id } }) end end -- Récupération de la list des backups local GETClient = net.HTTPClient() if dryrun then print('Mode DryRun -> La requète pour effacer ne sera pas éxécutée') end GETClient:request('http://127.0.0.1/api/service/backups', { success = function(response) if tonumber(response.status) == 200 then sortBackup(response.data) else print("Error " .. response.status) end end, error = function(err) print('error = ' .. err) end, headers = { ["content-type"] = 'application/x-www-form-urlencoded;', ["authorization"] = 'Basic '..password } }); Nicolas 3
pepite Posté(e) le 3 décembre 2016 Signaler Posté(e) le 3 décembre 2016 YEs @Nikko, un grand merci, c'est top !!! encore en 4.100 mais on garde sous le coude lol T'es au top.. Je mettrai à jour le post API des que possible
pepite Posté(e) le 3 décembre 2016 Signaler Posté(e) le 3 décembre 2016 @Nikko J'ai essaye cela en lua, mais rien, ca importe pas la librairie. Donc pas de mime dans le lua fibaro ? local mime = require( "mime" ) local encodedString = mime.b64("Hello World"); print( mime.unb64( encodedString ) ) L'erreur [DEBUG] 22:11:31: line 47: attempt to call global 'require' (a nil value)
Lazer Posté(e) le 3 décembre 2016 Signaler Posté(e) le 3 décembre 2016 require fait parti des fonctions LUA bloquées par Fibaro
Nikko Posté(e) le 3 décembre 2016 Auteur Signaler Posté(e) le 3 décembre 2016 @pepite: Source: https://gist.github.com/bortels/1436940 local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- encoding function enc(data) return ((data:gsub('.', function(x) local r,b='',x:byte() for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end return r; end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) if (#x < 6) then return '' end local c=0 for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end return b:sub(c+1,c+1) end)..({ '', '==', '=' })[#data%3+1]) end print(enc('pepite@domotique-fibaro.fr:jolipassword')) 3
pepite Posté(e) le 3 décembre 2016 Signaler Posté(e) le 3 décembre 2016 Merci !!!! heur c'était plus simple avec le require non ? allez je teste hihi
pepite Posté(e) le 3 décembre 2016 Signaler Posté(e) le 3 décembre 2016 Bon, ben ok pour l'encoder, mais pas le decode, j'ai juste repique le code du GitHub ;-) local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- encoding function enc(data) return ((data:gsub('.', function(x) local r,b='',x:byte() for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end return r; end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) if (#x < 6) then return '' end local c=0 for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end return b:sub(c+1,c+1) end)..({ '', '==', '=' })[#data%3+1]) end -- decoding function dec(data) data = string.gsub(data, '[^'..b..'=]', '') return (data:gsub('.', function(x) if (x == '=') then return '' end local r,f='',(b:find(x)-1) for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end return r; end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) if (#x ~= 8) then return '' end local c=0 for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(7-i) or 0) end return string.char(c) end)) end print(enc('pepite@domotique-fibaro.fr:jolipassword')) print(dec('cGVwaXRlQGRvbW90aXF1ZS1maWJhcm8uZnI6am9saXBhc3N3b3Jk')) Ok pour l'encode, mais pas le decode lol DEBUG] 22:45:54: cGVwaXRlQGRvbW90aXF1ZS1maWJhcm8uZnI6am9saXBhc3N3b3Jk [DEBUG] 22:45:54: 8284:2 2868:48:2�341098�39�586480::<892
pepite Posté(e) le 3 décembre 2016 Signaler Posté(e) le 3 décembre 2016 Fonctionne parfaitement avec celui-ci :http://lua-users.org/wiki/BaseSixtyFour -- character table string local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- encoding function enc(data) return ((data:gsub('.', function(x) local r,b='',x:byte() for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end return r; end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) if (#x < 6) then return '' end local c=0 for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end return b:sub(c+1,c+1) end)..({ '', '==', '=' })[#data%3+1]) end -- decoding function dec(data) data = string.gsub(data, '[^'..b..'=]', '') return (data:gsub('.', function(x) if (x == '=') then return '' end local r,f='',(b:find(x)-1) for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end return r; end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) if (#x ~= 8) then return '' end local c=0 for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end return string.char(c) end)) end -- command line if not called as library if (arg ~= nil) then local func = 'enc' for n,v in ipairs(arg) do if (n > 0) then if (v == "-h") then print "base64.lua [-e] [-d] text/data" break elseif (v == "-e") then func = 'enc' elseif (v == "-d") then func = 'dec' else print(_G[func](v)) end end end end print(enc('pepite@domotique-fibaro.fr:jolipassword')) print(dec('cGVwaXRlQGRvbW90aXF1ZS1maWJhcm8uZnI6am9saXBhc3N3b3Jk')) Le debug print(enc('pepite@domotique-fibaro.fr:jolipassword')) print(dec('cGVwaXRlQGRvbW90aXF1ZS1maWJhcm8uZnI6am9saXBhc3N3b3Jk'))
Messages recommandés