Quick App - Monitoring Nas Synology
Je vous propose un QA pour le monitoring de la HC3.
Ce QA a été encore une fois réalisé avec l'aide de mon neveu (et oui je suis en train de la convertir).
Il peut certainement être optimisé mais il fait le job. Je n'ai pas rencontré de bug.
Vous pouvez le modifier et l'améliorer à votre guise.
Il a les mêmes fonctions que celui de la HC2 dont on s'est largement inspiré.
Utilisation :
-- Créer deux variables "IPAddress" & "TCPPort"
-- Renseigner votre "LOGIN" et votre "PASSWORD"
-- Pour la fonction WOL, utiliser le QA WOL de Fibaro et appellé-le avec la commande:
-- ==> fibaro.call(ID, "turnOn")
EDIT: Voir le Header
EDIT: Nouvelle version du QuickApp - Monitoring Nas Synology. Ajout des boutons pour l'éjection des disques durs connectés en USB sur les NAS. J'ai ajouté 4 boutons. Je pense que cela sera suffisant. Pour en ajouter d'autres, il suffit de suivre les commentaires dans la partie "FONCTION EJECT USB" du code. Les boutons se nomment USB Disk 1 à 4.
Lorsque l'un des disques est déconnecté, les boutons se déplacent vers la gauche ( USB Disk 1 / USB Disk 2/ USB Disk 3/ No Disk ==> On élève le USB Disk 2 ==> / USB Disk 1 / USB Disk 3/ No Disk / No Disk).
Je n'ai pas rencontré de bug.
Le code:
-- QuickApp Monitoring Nas Synology pour Fibaro HC3
-- Generic device type have no default actions to handle
-- HISTORIQUE
-- Adapté de https://www.domotique-fibaro.fr/topic/5682-synology-monitoring/
-- v2.4 (29/08/2015 - jojo) : première version
-- merci à Krikroff, Lazer, Steven, mprinfo, FDP2
-- v2.41 (02/09/2015 - jojo) : slider pour double click
-- V1.0 (14/05/2020) pour Home Center 3 par fredokl et Maxime pour le site www.domotique-fibaro.fr
-- V1.1 (15/05/2020) pour Home Center 3 par fredokl et Maxime pour le site www.domotique-fibaro.fr
-- Ajout du push pour avertir que le serveur n'est plus connecté. Ligne 409 de ce code
-- V1.2 (27/05/2020) pour Home Center 3 par fredokl et Maxime pour le site www.domotique-fibaro.fr
-- Transformation du QA en "com.fibaro.genericDevice" à la place de "Commutateur binaire"
-- Ajout des icônes "serveur allumé" et "serveur éteint"
-- V1.3 (29/05/2020) pour Home Center 3 par fredokl et Maxime pour le site www.domotique-fibaro.fr
-- Ajout des boutons "Eject Disk"
-- Changement rafraîchissement automatique (toute les minutes ==> Check tout le NAS et toutes les 10 secondes ==> Check les Disk USB)
-- Améliorations du code
-- Lien topic: https://www.domotique-fibaro.fr/topic/14308-quick-app-monitoring-serveur-nas-synology/
-- Utilisation:
-- La connexion au NAS se fait par HTTP
-- Créer deux variables "IPAddress" & "TCPPort"
-- Renseigner votre "LOGIN" et votre "PASSWORD"
-- Pour la fonction WOL, utiliser le QA WOL de Fibaro et appellé-le avec la commande:
-- ==> fibaro.call(ID, "turnOn")
-- Vous pouvez le modifier et l'améliorer à votre guise.
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
-- PARAMÈTRES UTILISATEUR --
-------------------------------------------------------------------------------------------
-- System variables
function QuickApp:onInit()
__TAG = "QA_"..plugin.mainDeviceId.."_DS 416 PLAY"
self:trace("==========================================")
self:debug("onInit")
-- User configurable variables
self.login = "login" -- votre login DSM
self.password = "Password" -- votre mot de psse DSM
self.ip = self:getVariable('IPAddress');
self.port = self:getVariable('TCPPort');
self.http = net.HTTPClient({ timeout = 10000 })
self.diskusblistid = {}
self.diskusblistname = {}
self.API_AUTH_ERROR_CODE = {
[0] = "Sans erreur.",
[100] = "Erreur inconnue.",
[101] = "Compte non spécifié.",
[400] = "Mot de passe invalide.",
[401] = "Compte désactivé.",
[402] = "Permission refusée.",
[403] = "Unique mot de passe non spécifié.",
[404] = "Autentification erronée."
};
self.API_RECORD_ERROR_CODE = {
[400] = "Exécution ratée.",
};
self.nbmsg = 0
self.timerOn = false
self.isCheckin = false
self.nbCheck = 0
self:autoCheck()
end
--------------------------------------------------------------------------------------
-- WAKE ON LAN
--------------------------------------------------------------------------------------
function QuickApp:uiWoLOnR()
fibaro.call(47, "turnOn")
end
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
-- == NE RIEN MODIFIER À PARTIR D'ICI ==
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
-- FONCTION GETRequest: Connexion GET
--------------------------------------------------------------------------------------
function QuickApp:GETRequest(payload, callBack)
--self:trace("Commande GETRequest")
local url = "http://" ..self.ip ..":" ..self.port ..payload
self.http:request(url,
{
options= {
headers= {
["Connection"] = "keep-alive",
["Accept"] = "application/json"
},
method = "GET"
},
success = function(response)
self.nbmsg = self.nbmsg + 1
if callBack then callBack(response.data) end
end,
error = function(message)
self:trace("error:" ..json.encode(message))
self.nbmsg = 0
self.timerOn = false
end
})
end
--------------------------------------------------------------------------------------
-- FONCTION EJECT USB
--------------------------------------------------------------------------------------
-- Refresh USB Disk
function QuickApp:refreshUSBdisk()
payload = "/webapi"..self.cgiUsed_sys.."?api="..self.apiStorage_usb.."&version=1&method=list&_sid="..self.SID;
self:GETRequest(payload, function(data)
jsonTable = json.decode(data);
if jsonTable.success == true then
local devices = jsonTable.data.devices
self.diskusblistid = {}
self.diskusblistname = {}
for k,v in pairs(devices) do
table.insert(self.diskusblistid, v.dev_id)
table.insert(self.diskusblistname, v.dev_title)
end
self:trace("refreshUSBdisk")
self:updateView("btn6", "text", self:getDiskName(self.diskusblistname[1])) -- Pour ajouter des boutons copier la ligne puis
self:updateView("btn7", "text", self:getDiskName(self.diskusblistname[2])) -- changer les id pour ajouter des disks.
self:updateView("btn8", "text", self:getDiskName(self.diskusblistname[3])) -- Pour supprimer un boutons ==> supprimer une ligne
self:updateView("btn9", "text", self:getDiskName(self.diskusblistname[4]))
--self:updateView("btn10", "text", self:getDiskName(self.diskusblistname[5])) -- Exemple bouton en plus
self:trace("==========================================")
end
end)
end
-- Eject USB Disk en fonction du diskID et refresh juste après
function QuickApp:ejectUSBdisk(diskID)
payload = "/webapi"..self.cgiUsed_sys.."?api="..self.apiStorage_usb.."&version=1&method=eject&dev_id="..diskID.."&_sid="..self.SID;
self:GETRequest(payload, function(data)
jsonTable = json.decode(data);
if jsonTable.success == true then
self:trace("==========================================")
self:trace("Disk: "..diskID.." éjecté")
self:refreshUSBdisk()
end
end)
end
-- Affiche des noms sur les boutons
function QuickApp:getDiskName(text)
local res= "No Disk "
if text then res = text end
return res
end
-- Eject Disk vérification présence disk
function QuickApp:ejectDisk(numero)
local diskID = self.diskusblistid[numero]
if diskID then
self:CheckConnect(
function()
if self.isCheckin == false then
self.isCheckin = true
self:DoAction(function () self:ejectUSBdisk(diskID) end, 2)
end
end)
end
end
-- Boutons Eject Disk
function QuickApp:uiEject1OnP(event) self:ejectDisk(1) end
function QuickApp:uiEject2OnP(event) self:ejectDisk(2) end
function QuickApp:uiEject3OnP(event) self:ejectDisk(3) end
function QuickApp:uiEject4OnP(event) self:ejectDisk(4) end
--function QuickApp:uiEject5OnP(event) self:ejectDisk(5) end -- Ajouter ligne pour commande bouton
--------------------------------------------------------------------------------------
-- AUTHORISATION CONNEXION NAS
--------------------------------------------------------------------------------------
function QuickApp:DoAction(action, nbmsgtotal)
--self:trace("Test avant ok connected")
self.timerOn = true
-- API & informations disponibles
payload = "/webapi/query.cgi?api=SYNO.API.Info&method=Query&version=1&query=SYNO.API.Auth"
self:GETRequest(payload,
function (data)
jsonTable = json.decode(data)
self.version = jsonTable.data["SYNO.API.Auth"].maxVersion
if self.version >= 2 then
self:trace("Version API Synology OK")
self.pathAuth = jsonTable.data["SYNO.API.Auth"].path
self.cgiUsed_cpu_mem = "/entry.cgi"
self.cgiUsed_sys= self.cgiUsed_cpu_mem
self.cgiUsed_temp = self.cgiUsed_cpu_mem
self.cgiUsed_vols = self.cgiUsed_cpu_mem
self.apiUsed_cpu_mem = "SYNO.Core.System.Utilization"
self.apiUsed_temp_system = "SYNO.Core.System"
self.apiUsed_sys= self.apiUsed_temp_system;
self.apiUsed_temp_disk = self.apiUsed_temp_system
self.apiUsed_vols = self.apiUsed_temp_system
self.apiMethod_cpu_mem="get"
self.apiMethod_temp = "info"
self.apiMethod_vols = self.apiMethod_temp
self.apiStorage_usb= "SYNO.Core.ExternalDevice.Storage.USB"
if self.version < 6 then
self.cgiUsed_cpu_mem = "/dsm/system_loading.cgi"
self.cgiUsed_sys="/dsm/system.cgi";
self.cgiUsed_temp = "/dsm/info.cgi"
self.cgiUsed_vols = "/dsm/volume.cgi"
self.apiUsed_cpu_mem = "SYNO.DSM.SystemLoading"
self.apiUsed_temp_system = "SYNO.DSM.Info"
self.apiUsed_temp_disk = ""
self.apiUsed_vols = "SYNO.DSM.Volume"
self.apiMethod_cpu_mem = "getinfo"
self.apiMethod_temp = self.apiMethod_cpu_mem
self.apiMethod_vols = "list"
self.apiUsed_sys="SYNO.DSM.System";
end
end
self:GetSid_Send(action)
self:timer(nbmsgtotal + 2)
end)
end
--------------------------------------------------------------------------------------
-- FONCTION GetInfo: RÉCUPÉRATION DES DONNÉES
--------------------------------------------------------------------------------------
function QuickApp:GetInfo(onlyDisk)
self.timercount = 1000
if onlyDisk == false then
-- CPU info du DSM
payload = "/webapi"..self.cgiUsed_cpu_mem.."?api="..self.apiUsed_cpu_mem.."&version=1&method="..self.apiMethod_cpu_mem.."&type=current&_sid="..self.SID;
self:GETRequest(payload,
function (data)
jsonTable = json.decode(data);
if jsonTable.success == true then
info_cpu = jsonTable.data.cpu;
load_mem = jsonTable.data.memory.real_usage;
self:trace("Memory: "..load_mem.."%");
info_cpu_memory = "Memory: "..load_mem.."% ";
load_cpu = 0;
if (self.version < 6) then
load_cpu = info_cpu.user*100;
else
load_cpu = info_cpu.other_load+info_cpu.system_load+info_cpu.user_load;
end
self:trace("CPU: "..load_cpu.."%")
info_cpu_memory = info_cpu_memory.."CPU: "..load_cpu.."%";
self:updateView("lbl3", "text", "Memoire: " ..load_mem .."% " .."CPU: " ..load_cpu .."%")
self:trace("==========================================")
end
end)
-- Info Température Système info du DSM
payload = "/webapi"..self.cgiUsed_temp.."?api="..self.apiUsed_temp_system.."&version=1&method="..self.apiMethod_temp.."&_sid="..self.SID;
self:GETRequest(payload,
function (data)
jsonTable = json.decode(data);
if jsonTable.success == true then
if jsonTable.data.sys_temp ~= nil then
temp_system = "Température du Système: " ..jsonTable.data.sys_temp.."°C";
else
temp_system = "Système: N/A";
end
self:trace(temp_system);
self:updateView("lbl4", "text", temp_system)
end
end)
-- Info Température des disques
-- Prépare string
temp_disks = "";
payload = "/webapi"..self.cgiUsed_temp.."?api="..self.apiUsed_temp_disk.."&version=2&method="..self.apiMethod_temp.."&type=storage&_sid="..self.SID;
self:GETRequest(payload,
function (data)
jsonTable = json.decode(data);
if jsonTable.success == true then
local disk_tab = jsonTable.data.hdd_info;
for nb = 1, #disk_tab do
temp_disks = temp_disks..disk_tab[nb].diskno..": "..disk_tab[nb].temp.."°C ";
end
self:trace("Température des Disques: "..temp_disks);
self:updateView("lbl5", "text", temp_disks)
end
end)
-- Info taille des disques
-- Prépare string
vols_load = "";
payload = "/webapi"..self.cgiUsed_vols.."?api="..self.apiUsed_vols.."&version=1&method="..self.apiMethod_vols.."&type=storage&_sid="..self.SID;
self:GETRequest(payload,
function (data)
jsonTable = json.decode(data);
if jsonTable.success == true then
local vols_tab = jsonTable.data.vol_info;
for nb = #vols_tab, 1, -1 do
used_size_vol = vols_tab[nb].used_size;
total_size_vol = vols_tab[nb].total_size;
occupied_size = self:round(used_size_vol / total_size_vol * 100);
vols_load = vols_load..vols_tab[nb].name..": "..occupied_size.."% ";
end
self:trace("Taille des Volumes: "..vols_load);
self:updateView("lbl6", "text", vols_load)
end
end)
end
--Refresh button disk
self:refreshUSBdisk()
-- Affichage IP Serveur
self:trace("IP Serveur ", "Serveur connecté: " ..self.ip ..":" ..self.port)
self:updateView("lbl1", "text", "Serveur connecté: " ..self.ip ..":" ..self.port)
end
--------------------------------------------------------------------------------------
-- FONCTION POUR ARRONDIR LES POURCENTAGES
--------------------------------------------------------------------------------------
function QuickApp:round(num)
local a = math.floor(num*100 + 0.5)/ 100;
return a,string.format("%.2f",a);
end
--------------------------------------------------------------------------------------
-- DÉCONNEXION
--------------------------------------------------------------------------------------
function QuickApp:Disconnect()
payload = "/webapi/"..self.pathAuth.."?api=SYNO.API.Auth&method=Logout&version=2&session=DSM&_sid="..self.SID;
self:GETRequest(payload, function()end);
end
--------------------------------------------------------------------------------------
-- TIMER
--------------------------------------------------------------------------------------
function QuickApp:timer(nbmsgtotal)
if self.timerOn then
if self.nbmsg < nbmsgtotal then fibaro.setTimeout(2000, function() self:timer(nbmsgtotal) end)
else
self:Disconnect()
self.nbmsg = 0
self.timerOn = false
self.isCheckin = false
end
end
end
--------------------------------------------------------------------------------------
-- REFRESH
--------------------------------------------------------------------------------------
function QuickApp:autoCheck()
self.nbCheck = self.nbCheck + 1
if self.nbCheck%6 == 0 or self.nbCheck == 1 then
onlyDisk = false
nbOperation = 5
else
onlyDisk = true
nbOperation = 1
end
self:CheckAll(onlyDisk, nbOperation)
fibaro.setTimeout(1000*10, function() self:autoCheck() end) --10 secondes
end
--------------------------------------------------------------------------------------
-- VÉRIFICATION DE TOUS LES ÉLÉMENTS
--------------------------------------------------------------------------------------
function QuickApp:CheckAll(onlyDisk, nbOperation)
self:CheckConnect(
function()
if self.isCheckin == false then
self.isCheckin = true
self:DoAction(function () self:GetInfo(onlyDisk) end, nbOperation)
end
end)
heure = os.date("%H:%M:%S")
date = os.date("%d/%m")
dateheure = string.format(" %s à %s", date, heure)
self:updateView("lbl7", "text", "Dernière vérification: "..dateheure)
end
--------------------------------------------------------------------------------------
-- CRÉATION D'UN NOUVEAU SID ET ENVOI DES COMMANDES
--------------------------------------------------------------------------------------
function QuickApp:GetSid_Send(callBack)
payload = "/webapi/"..self.pathAuth.."?api=SYNO.API.Auth&method=Login&version=2&account="..self.login.."&passwd="..self.password.."&session=DSM&format=sid";
self:GETRequest(payload,
function (data)
jsonTable = json.decode(data);
if jsonTable.success == true then
self.SID = jsonTable.data.sid;
callBack()
end
end)
end
--------------------------------------------------------------------------------------
-- BOUTON RAFRAÎCHISSEMENT
--------------------------------------------------------------------------------------
function QuickApp:uiCheckOnR(event)
self:CheckAll(false, 5)
end
-- Check Connect
function QuickApp:CheckConnect(callBack)
self.tcp = net.TCPSocket({timeout = 1000})
self.tcp:connect(self.ip, tonumber(self.port),
{
success = function()
self:trace("Check Connect OK")
self:updateView("lbl2", "text", "Serveur: Allumé")
fibaro.setGlobalVariable("Syno_Status1", "1")
self:updateProperty("deviceIcon", 1042) -- Mettre ici le code pour l'icone allumé
self.tcp:close()
if callBack then callBack() end
end,
error = function(message)
self:trace("erreur " ..message)
self:updateProperty("deviceIcon", 1043) -- mettre ici le code pour l'icone éteint
self:updateView("lbl1", "text", "Serveur connecté: N/A")
self:updateView("lbl2", "text", "Serveur: Éteint")
self:updateView("lbl3", "text", "Mémoire: N/A")
self:updateView("lbl4", "text", "Température Système: NA")
self:updateView("lbl5", "text", "Température diques: N/A")
self:updateView("lbl6", "text", "Volume des disques: N/A")
fibaro.setGlobalVariable("Syno_Status1", "0")
--------------------------------------------------------------------------------------
-- ENVOI PUSH TOUTES LES DIX MINUTES
--------------------------------------------------------------------------------------
if self.nbCheck%60 == 0 then fibaro.alert("push", {26}, "NAS Synology DS 416 Play est éteint: " ..os.date("%H:%M:%S")) end
end
})
end
--------------------------------------------------------------------------------------
-- REDÉMARRAGE DU DISK STATION
--------------------------------------------------------------------------------------
-- Bouton Reboot
function QuickApp:uiRebootOnP(event)
self:CheckConnect(
function()
if self.isCheckin == false then
self.isCheckin = true
self:DoAction(function () self:Reboot() end, 1)
end
end)
end
-- Code Reboot
function QuickApp:Reboot()
payload = "/webapi"..self.cgiUsed_sys.."?api="..self.apiUsed_sys.."&version=1&method=reboot&_sid="..self.SID;
self:GETRequest(payload, function(data)
jsonTable = json.decode(data);
if jsonTable.success == true then
self:trace("Redémarrage Disk Station Synology OK");
end
end)
end
--------------------------------------------------------------------------------------
-- ARRÊT DU DISK STATION
--------------------------------------------------------------------------------------
-- ShutDown the disk station
function QuickApp:uiShutdownOnP(event)
self:CheckConnect(
function()
if self.isCheckin == false then
self.isCheckin = true
self:DoAction(function () self:ShutDown() end, 1)
end
end)
end
function QuickApp:ShutDown()
payload = "/webapi"..self.cgiUsed_sys.."?api="..self.apiUsed_sys.."&version=1&method=shutdown&_sid="..self.SID;
self:GETRequest(payload, function(data)
jsonTable = json.decode(data);
if jsonTable.success == true then
self:trace("Le Disk Station s'est arrêté");
end
end)
end
--------------------------------------------------------------------------------------
-- FIN DU CODE --
--------------------------------------------------------------------------------------
QuickApp:
QA-NAS_Synology.fqa
Icônes: