Page 28 sur 28

Re: [DzVents] LiveBox 3 et 4

Publié : 07 sept. 2024, 09:50
par pierrotori
voici le script migré en shellCommandResponses
celui-ci tourne sous docker, il faudra modifier quelques path

Code : Tout sélectionner

--[[
    Prérequis :
    Domoticz v3.8837 or later (dzVents version 2.4 or later)

    Sources :   https://www.alex-braga.fr/ressources_externe/xdslbox_3.4.10.sh
                https://github.com/rene-d/sysbus
                https://github.com/NextDom/plugin-livebox/

    Livebox 3/4 stats

                https://easydomoticz.com/forum/viewtopic.php?f=17&t=7247
                https://github.com/papo-o/domoticz_scripts/new/master/dzVents/scripts/livebox.lua
                https://pon.fr/dzvents-toutes-les-infos-de-la-livebox-en-un-seul-script/

-- Authors  ----------------------------------------------------------------
    V1.0 -  Neutrino -     Domoticz
    V1.1 -  Neutrino -     Activation/désactivation du WiFi
    V1.2 -  papoo -        Liste des n derniers appels manqués, sans réponse, réussis et surveillance périphériques des connectés/déconnectés
    V1.3 -  Neutrino -     Possibilité de purger le journal d'appels
    V1.4 -  papoo -        Possibilité de rebooter la Livebox
    V1.5 -  papoo -        Correction non mise à jour des devices après RAZ de la liste des appels
    V1.6 -  papoo -        Correction horodatage heures d'appel à GMT+2
    V1.7 -  papoo -        Affichage des noms connus via fichiers de contacts
    V1.8 -  Neutrino -     Support de la Livebox 3 Play, gestion heures d'été/heure d'hiver
    V1.9 -  Neutrino -     Prise en charge du Wifi 5 GHz de la Livebox 3
    V1.10 - Neutrino -     Gestion fichier contacts inexistant, gestion périphériques différentes, version du firmware, correction de bugs,
                           Optimisation du nombre de requêtes
    V1.11 - Neutrino       Uptime de la box et non de la connexion dsl
    V1.12 - JCLB           Faire sonner le téléphone
    V1.13 - Neutrino       Correction de bugs
    V1.14 - papoo          Notification appel manqué
    V1.15 - papoo          Correction de bugs
    V1.20 - pierrotori     Livebox5 avec docker gestion 5ghz avec eth4
    V1.21 - pierrotori     Compteur total update en jour et non en fonction de fetchIntervalMins
    V1.22 - pierrotori     Migration os.capture en shellCommandResponses asynchrone
    V1.23 - pierrotori     Migration fichier de verrou vers persistent data
]]--
-- Variables à modifier ------------------------------------------------
local adresseLB         = 'XXX.XXX.X.X' --Adresse IP de votre Livebox 4 ou 5
local password          = "XXXXXXXX"
local tmpDir            = "/opt/domoticz/userdata/scripts/dzVents/data" --répertoire temporaire, idéal en RAM
local OutputD           = tmpDir.."/LiveboxD.txt"
local CookiesD          = tmpDir.."/CookiesD.txt"
local OutputA           = tmpDir.."/LiveboxA.txt"
local CookiesA          = tmpDir.."/CookiesA.txt"
local fichier_contacts  = "/opt/domoticz/userdata/scripts/dzVents/scripts/contacts.json"
local liveBox3          = false --true si vous avez une liveBox3/play

-- Domoticz devices
local IPWAN             = "ipv4" --"IP WAN" -- Nom du capteur Text IP WAN, nil si non utilisé
local IPv6WAN           = "ipv6" --"IPv6 WAN" -- Nom du capteur Text IPv6 WAN, nil si non utilisé
local UptimeLB          = "Temps total Livebox" --"Uptime Livebox"  -- Nom du capteur Text Uptime Livebox, nil si non utilisé
local internet          = "Internet" --"Internet"  -- Nom du capteur Interrupteur Internet, nil si non utilisé
local VoIP              = nil --"VoIP"  -- Nom du capteur Interrupteur VoIP, nil si non utilisé
local ServiceTV         = nil --"Service TV"  -- Nom du capteur Interrupteur Service TV, nil si non utilisé
local wifi24            = "Livebox_wifi2G" --"WiFi 2.4"  -- Nom du capteur Interrupteur wifi 2.4Ghz, nil si non utilisé
local wifi5             = "Livebox_wifi5G" --"WiFi 5"  -- Nom du capteur Interrupteur wifi 5Ghz, nil si non utilisé
local firmware          = "firmware" --"Firmware LB" -- Nom du capteur Text Firmware LB, nil si non utilisé
local DernierAppel      = nil --"Dernier Appel" -- Nom du capteur Text Dernier Appel, nil si non utilisé
local missedCall        = "Appels manqués" -- Nom du capteur Text appels manqués, nil si non utilisé
local nbMissedCall      = 3 -- Nombre d'appels manqués à afficher
local failedCall        = "Appels sans réponse" -- nil -- Nom du capteur Text appels sans réponse, nil si non utilisé
local nbFailedCall      = 3 -- Nombre d'appels sans réponse à afficher
local succeededCall     = "Appels réussis" -- Nom du capteur Text appels réussis, nil si non utilisé
local nbSucceededCall   = 3 -- Nombre d'appels réussis à afficher
local clearCallList     = "Effacer liste appels" -- Nom du capteur Interrupteur PushOn clearCallList
local reboot            = "Reboot Livebox" -- Nom du capteur Interrupteur PushOn reboot
local sonner            = "Sonner" -- "Sonner" -- Nom du capteur Interrupteur PushOn faire sonner tel
local notifyMissedCall  = true

local devices_livebox_mac_adress = { -- MAC ADDRESS des périphériques à surveiller
                                    }

-- Capteurs pour connexion xDSL seulement
local SyncATM = nil -- "Signal RxPower" -- Nom du capteur custom Synchro ATM down, nil si non utilisé
local SyncATMup = nil -- "Signal TxPower" -- Nom du capteur custom Synchro ATM up, nil si non utilisé
local Attn = nil -- Nom du capteur custom Attenuation de la ligne, nil si non utilisé
local MargedAttn = nil -- Nom du capteur custom Marge d'atténuation, nil si non utilisé
-- Livebox 4 seulement
local TransmitBlocks = nil  -- Nom du capteur Incremental Counter TransmitBlocks, nil si non utilisé
local ReceiveBlocks = nil  -- Nom du capteur Incremental Counter ReceiveBlocks, nil si non utilisé
local fetchIntervalMins = 5 --  intervalle de mise à jour.

local scriptName = 'Livebox5'
local scriptVersion = '2.23'

local f_dry_run = 'N'                -- (Y) pour tester le script sans activer réellement des dispositifs
local f_notification = "Y"           -- (Y) Active les f_notifications, (N) les désactive 
local f_logging = "N"			     -- (Y) donne le temps de chaque appel shellCommandResponses

local message = '.'

return {
	active = true,
	on = {
	timer = { 'every '..tostring(fetchIntervalMins)..' minutes' }, -- toutes les 5 minutes
	customEvents = { 'dt_livebox5' },
	shellCommandResponses = { 'cookies', 'livebox', 'connexion', 'volume', 'wifi', 'appel', 'reseau' },
	devices = {wifi24,wifi24,clearCallList,reboot,sonner}
	},
	data = {
		connexion 	= { initial = 0, maxItems = 1 },
		volume 		= { initial = 0, maxItems = 1 },
		wifi 		= { initial = 0, maxItems = 1 },
		appel 		= { initial = 0, maxItems = 1 },
		reseau 		= { initial = 0, maxItems = 1 },
	},
    logging = {
        -- level    =   domoticz.LOG_DEBUG, -- Uncomment to override the dzVents global logging setting
        -- level    =   domoticz.LOG_INFO, -- Seulement un niveau peut être actif; commenter les autres
        -- level    =   domoticz.LOG_ERROR,
        -- level    =   domoticz.LOG_MODULE_EXEC_INFO,
        marker = scriptName..' '..scriptVersion
    },	

execute = function(dz, item)
	local notificationTable = dz.NSS_HTTP  --[[ Systèmes de f_notification disponibles :
			NSS_GOOGLE_CLOUD_MESSAGING NSS_HTTP NSS_KODI NSS_LOGITECH_MEDIASERVER NSS_NMA NSS_PROWL NSS_PUSHALOT NSS_PUSHBULLET NSS_PUSHOVER NSS_PUSHSAFER
			Pour une notification sur plusieurs systèmes, séparez les systèmes par une virgule et entourez l'ensemble par des {}.
			Exemple :{dz.NSS_TELEGRAM, dz.NSS_HTTP}
			--]]	

	-- SVP, ne rien changer sous cette ligne
	function os.capture(cmd, raw)
		local f = assert(io.popen(cmd, 'r'))
		local s = assert(f:read('*a'))
		f:close()
		if raw then return s end
		s = string.gsub(s, '^%s+', '')
		s = string.gsub(s, '%s+$', '')
		s = string.gsub(s, '[\n\r]+', ' ')
		return s
	end

	function disp_time(time)
		local days = math.floor(time/86400)
		local remaining = time % 86400
		local hours = math.floor(remaining/3600)
		remaining = remaining % 3600
		local minutes = math.floor(remaining/60)
		remaining = remaining % 60
		local seconds = remaining
		return string.format("%d:%02d:%02d:%02d",days,hours,minutes,seconds)
	end

	function traduction(str) -- supprime les accents de la chaîne str
		if (str) then
		str = string.gsub (str,"missed", "manqué")
		str = string.gsub (str,"failed", "échoué")
		str = string.gsub (str,"succeeded", "réussi")
		end
		return (str)
	end

	function get_timezone()
	  local now = os.time()
	  return os.difftime(now, os.time(os.date("!*t", now)))
	end

	function format_date(str) -- supprime les caractères T et Z de la chaîne str  et corrige l'heure suivant le fuseau horaire
		if (str) then
			_, _, A, M, j, h, m, s = string.find(str, "^(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)Z$")
			if dz.time.isdst == true then --test si heure d'été
				h = h + 1 + get_timezone()/3600 
			else
				 h = h + get_timezone()/3600
			end
			str= A.."-"..M.."-"..j.." - "..h..":"..m..":"..s
		end
		return (str)
	end

	function delta_date(str) -- supprime les caractères T et Z de la chaîne str  et corrige l'heure suivant le fuseau horaire
		diff = 0
		if (str) then
			_, _, A, M, j, h, m, s = string.find(str, "^(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)Z$")
			h = h + get_timezone()/3600
			-- ajout gestion livebox  internet down
			if ( str ~= "0001-01-01T00:00:00Z" ) then
				diff = os.time()-os.time{year=A, month=M, day=j, hour=h, min=m, sec=s}
			end
		end
		return (disp_time(diff))
	end

	function ReverseTable(t)
		local reversedTable = {}
		local itemCount = #t
		for k, v in ipairs(t) do
			reversedTable[itemCount + 1 - k] = v
		end
		return reversedTable
	end

	function searchName(contacts, phoneNumber)
		name = phoneNumber
		for index, variable in pairs(contacts) do
			if variable.Phone == phoneNumber then
				name = variable.Name
				break
			end
		end
		return name
	end

	function searchKey(children, mac)
		key = -1
		if children then
			for index, variable in pairs(children) do
				if variable.Key == mac then
					key = index
					break
				end
			end
		end
		return key
	end
	
	local function readLuaFromJsonFile(fileName)
		local file = io.open(fileName, 'r')
		if file then
			local contents = file:read('*a')
			local lua_value = dz.utils.fromJSON(contents)
			io.close(file)
			return lua_value
		end
		return nil
	end

	local function status_check()
		-- si erreur precedente alors logout et remove cookies
		if dz.data.connexion == 1 then
			dz.log('Erreur data connexion', dz.LOG_ERROR)
			dz.data.connexion = 0
		end
		if dz.data.volume == 1 then
			dz.log('Erreur data volume', dz.LOG_ERROR)
			dz.data.volume = 0
		end		
		if dz.data.wifi == 1 then
			dz.log('Erreur data wifi', dz.LOG_ERROR)
			dz.data.wifi = 0
		end
		if dz.data.appel == 1 then
			dz.log('Erreur data appel', dz.LOG_ERROR)
			dz.data.appel = 0
		end
		if dz.data.reseau == 1 then
			dz.log('Erreur data reseau', dz.LOG_ERROR)
			dz.data.reseau = 0
		end

		if dz.utils.fileExists(OutputD) and dz.utils.fileExists(CookiesD) then
			dz.log('Erreur init full', dz.LOG_ERROR)
			--Déconnexion et suppression des fichiers temporaires
			os.execute("curl -m1 -s -b "..CookiesD.." -X POST http://"..adresseLB.."/logout")
			os.execute('rm "'..CookiesD..'" "'..OutputD..'"')
		elseif dz.utils.fileExists(OutputD) then
			dz.log('Erreur init :'..OutputD, dz.LOG_ERROR)
			os.execute('rm "'..OutputD..'"')
		elseif dz.utils.fileExists(CookiesD) then
			dz.log('Erreur init :'..CookiesD, dz.LOG_ERROR)
			os.execute('rm "'..CookiesD..'"')
		end
	end
	
	local function logout(type)
		--gestion déconnexion asynchrone
		flag=0
		if dz.data.connexion == 1 and "connexion" ~= type then flag=1 end
		if dz.data.volume == 1 and "volume" ~= type then flag=1 end
		if dz.data.wifi == 1 and "wifi" ~= type then flag=1 end
		if dz.data.appel == 1 and "appel" ~= type then flag=1 end
		if dz.data.reseau == 1 and "reseau" ~= type then flag=1 end		
		if flag == 0 then
			dz.log('Fermeture session sur trigger : '..type, dz.LOG_INFO)
			os.execute("curl -m1 -s -b "..CookiesD.." -X POST http://"..adresseLB.."/logout")
			os.execute('rm "'..CookiesD..'" "'..OutputD..'"')
		end
		return nil
	end
	
	-- PROGRAM STARTS
	dz.log('============== LIVEBOX 5 LOG ==================', dz.LOG_INFO)
	if item.isTimer then
		dz.log('Déclenchement timer', dz.LOG_DEBUG)
	elseif item.isShellCommandResponse then
		dz.log('Déclenchement ShellCommandResponse', dz.LOG_DEBUG)
	elseif item.isCustomEvent then
		dz.log('Déclenchement CustomEvents', dz.LOG_DEBUG)
	elseif item.isDevice then
		dz.log('Déclenchement Device', dz.LOG_DEBUG)
	else
		return
	end

	if item.isTimer or item.isCustomEvent then
		-- si problem on ferme la connection precedente
		status_check()
		--Connexion et récupération du cookies
		dz.executeShellCommand(
		{
		command = "curl -s -o \""..OutputD.."\" -X POST -c \""..CookiesD.."\" -H 'Content-Type: application/x-sah-ws-4-call+json' -H 'Authorization: X-Sah-Login' -d \"{\\\"service\\\":\\\"sah.Device.Information\\\",\\\"method\\\":\\\"createContext\\\",\\\"parameters\\\":{\\\"applicationName\\\":\\\"so_sdkut\\\",\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\""..password.."\\\"}}\" http://"..adresseLB.."/ws > /dev/null",
		callback = 'cookies',
		timeout = 10
		})
	end
	-- si un des isShellCommandResponse retourne erreur alors logout et remove cookies
	if item.isShellCommandResponse and not item.statusCode then
		-- si problem on ferme la connection precedente
		status_check()
		message="Problème Livebox5:"..item.trigger.."("..item.statusCode..")"
		if f_notification == "Y" then
			dz.helpers.generalNotify(dz, 'EXPLOIT', scriptName, message, 'telegram')
		end	
	end
	
	if item.isShellCommandResponse and item.statusCode and item.trigger == 'cookies' then
		--Lecture du cookies pour utilisation ultérieure
		dz.executeShellCommand(
			{
			command = "tail -n1 \""..OutputD.."\" | sed 's/{\"status\":0,\"data\":{\"contextID\":\"//1'| sed 's/\",//1' | sed 's/\"groups\":\"http,admin//1' | sed 's/\"}}//1'",
			callback = 'livebox',
			timeout = 10
			})
	end
	
	if item.isShellCommandResponse and item.statusCode and item.trigger == 'livebox' then
		if not item.ok then
			dz.log('Erreur récupération context', dz.LOG_ERROR)
			os.execute('rm "'..OutputD..'"')
		else
			myContextID = item.data
			dz.log('Context : '..myContextID, dz.LOG_DEBUG)
			--Données de connexion
			if SyncATM or SyncATMup or Attn or MargedAttn then
				dz.data.connexion = 1
				dz.executeShellCommand(
					{
					command = "curl -s -b \""..CookiesD.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..myContextID.."\" -d \"{\\\"service\\\":\\\"NeMo.Intf.data\\\",\\\"method\\\":\\\"getMIBs\\\",\\\"parameters\\\":{}}\" http://"..adresseLB.."/ws",
					callback = 'connexion',
					timeout = 10
					})			
			end
			-- Volume de données échangées
			if TransmitBlocks or ReceiveBlocks then
				dz.data.volume = 1
				dz.executeShellCommand(
					{
					command = "curl -s -b \""..CookiesD.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..myContextID.."\" -d \"{\\\"service\\\":\\\"NeMo.Intf.dsl0\\\",\\\"method\\\":\\\"getDSLStats\\\",\\\"parameters\\\":{}}\" http://"..adresseLB.."/ws",
					callback = 'volume',
					timeout = 10
					})						
			end
			--État WiFi
			if wifi24 or wifi5 then
				dz.data.wifi = 1
				dz.executeShellCommand(
					{
					command = "curl -s -b \""..CookiesD.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..myContextID.."\" -d \"{\\\"service\\\":\\\"NeMo.Intf.lan\\\",\\\"method\\\":\\\"getMIBs\\\",\\\"parameters\\\":{}}\" http://"..adresseLB.."/ws",
					callback = 'wifi',
					timeout = 10
					})
			end
			--Dernier Appel reçu ou émis
			if DernierAppel or missedCall or failedCall or succeededCall then
				dz.data.appel = 1
				dz.executeShellCommand(
					{
					command = "curl -s -b \""..CookiesD.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..myContextID.."\" -d \"{\\\"service\\\":\\\"VoiceService.VoiceApplication\\\",\\\"method\\\":\\\"getCallList\\\",\\\"parameters\\\":{}}\" http://"..adresseLB.."/ws",
					callback = 'appel',
					timeout = 10
					})
			end
			-- Etat du réseau
			if firmware or devices_livebox_mac_adress or ServiceTV or VoIP or UptimeLB then
				dz.data.reseau = 1
				dz.executeShellCommand(
					{
					command = "curl -s -b \""..CookiesD.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..myContextID.."\" -d \"{\\\"service\\\":\\\"Devices.Device.HGW\\\",\\\"method\\\":\\\"topology\\\",\\\"parameters\\\":{}}\" http://"..adresseLB.."/ws",
					callback = 'reseau',
					timeout = 10
					})			
			end
		end
	end

	if item.isShellCommandResponse and item.statusCode and item.trigger == 'connexion' then
		if f_logging == "Y" then 
			begin = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
		end
		if not item.ok or not item.isJSON then
			dz.log('Lecture de la MIBs impossible', dz.LOG_ERROR)
		else
			MIBs=item.data
			dz.log('MIBs : '..MIBs, dz.LOG_DEBUG)
			local lbAPIData = dz.utils.fromJSON(MIBs)
			if lbAPIData.status == nil or lbAPIData == nil then
				dz.log('Lecture de la MIBs impossible', dz.LOG_ERROR)
			else
				if SyncATM then dz.log('ATM Down: '..lbAPIData.status.gpon.veip0.SignalRxPower, dz.LOG_INFO)
				dz.devices(SyncATM).updateCustomSensor(lbAPIData.status.gpon.veip0.SignalRxPower/1000) end

				if SyncATMup then dz.log('ATM Up: '..lbAPIData.status.gpon.veip0.SignalTxPower, dz.LOG_INFO)
				dz.devices(SyncATMup).updateCustomSensor(lbAPIData.status.gpon.veip0.SignalTxPower/1000) end

				-- if Attn then dz.log('Attn : '..tostring(lbAPIData.status.dsl.dsl0.DownstreamLineAttenuation/10)..' dB', dz.LOG_INFO)
				-- dz.devices(Attn).updateCustomSensor(tostring(lbAPIData.status.dsl.dsl0.DownstreamLineAttenuation/10)) end

				-- if MargedAttn then dz.log('Marge d\'Attn : '..tostring(lbAPIData.status.dsl.dsl0.DownstreamNoiseMargin/10)..' dB', dz.LOG_INFO)
				-- dz.devices(MargedAttn).updateCustomSensor(tostring(lbAPIData.status.dsl.dsl0.DownstreamNoiseMargin/10)) end
			end
		end
		dz.data.connexion = 0
		logout("connexion")
		if f_logging == "Y" then 
			local millis = dz.helpers.osCommand('Connexion date +%s%3N|tr -d "\n"')
			dz.log("Temps Connexion : "..millis-begin, dz.LOG_INFO)
		end	
	end
	
	if item.isShellCommandResponse and item.statusCode and item.trigger == 'volume' then
		if f_logging == "Y" then 
			begin = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
		end
		if not item.ok or not item.isJSON then
			dz.log('Lecture de la DSLstats impossible', dz.LOG_ERROR)
		else		
			DSLstats=item.data
			dz.log('DSLstats : '..DSLstats, dz.LOG_DEBUG)
			local lbAPIDataDSL = dz.utils.fromJSON(DSLstats)
			if lbAPIDataDSL.status == nil then
				dz.log('Lecture de la MIBs DSL impossible', dz.LOG_ERROR)
			else
				dz.log("TransmitBlocks : "..lbAPIDataDSL.status.TransmitBlocks)
				if TransmitBlocks then dz.devices(TransmitBlocks).update(0,lbAPIDataDSL.status.TransmitBlocks) end
				dz.log("ReceiveBlocks : "..lbAPIDataDSL.status.ReceiveBlocks)
				if ReceiveBlocks then dz.devices(ReceiveBlocks).update(0,lbAPIDataDSL.status.ReceiveBlocks) end
			end
			dz.data.volume = 0
			logout("volume")
			if f_logging == "Y" then
				local millis = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
				dz.log("Temps Volume : "..millis-begin, dz.LOG_INFO)
			end
		end
	end

	if item.isShellCommandResponse and item.statusCode and item.trigger == 'wifi' then
		if f_logging == "Y" then 
			begin = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
		end
		if not item.ok or not item.isJSON then
			dz.log('Lecture de API Wifi impossible', dz.LOG_ERROR)
		else
			wifi=item.data
			dz.log('wifi : '..wifi, dz.LOG_DEBUG)
			local lbAPIDataWifi = dz.utils.fromJSON(wifi)
			
			if wifi24 then
				dz.log('Wifi 2.4 Ghz : '..lbAPIDataWifi.status.wlanvap.wl0.VAPStatus, dz.LOG_INFO)
				if (lbAPIDataWifi.status.wlanvap.wl0.VAPStatus == 'Up' and dz.devices(wifi24).active == false) then
					dz.devices(wifi24).switchOn().silent()
				elseif (lbAPIDataWifi.status.wlanvap.wl0.VAPStatus ~= 'Up' and dz.devices(wifi24).active) then
					dz.devices(wifi24).switchOff().silent()
				end
			end

			if wifi5 then
				-- if (lbAPIDataWifi.status.wlanvap.eth6) then
				if (lbAPIDataWifi.status.wlanvap.eth4) then
					dz.log('Wifi 5 Ghz : '..lbAPIDataWifi.status.wlanvap.eth4.VAPStatus, dz.LOG_INFO)
					if (lbAPIDataWifi.status.wlanvap.eth4.VAPStatus == 'Up' and dz.devices(wifi5).active == false) then
						dz.devices(wifi5).switchOn().silent()
					elseif (lbAPIDataWifi.status.wlanvap.eth4.VAPStatus ~= 'Up' and dz.devices(wifi5).active) then
						dz.devices(wifi5).switchOff().silent()
					end
				else
					--support de la livebox3
					dz.log('Wifi 5 Ghz : '..lbAPIDataWifi.status.wlanvap.wl1.VAPStatus, dz.LOG_INFO)
					if (lbAPIDataWifi.status.wlanvap.wl1.VAPStatus == 'Up' and dz.devices(wifi5).active == false) then
						dz.devices(wifi5).switchOn().silent()
					elseif (lbAPIDataWifi.status.wlanvap.wl1.VAPStatus ~= 'Up' and dz.devices(wifi5).active) then
						dz.devices(wifi5).switchOff().silent()
					end
				end
			end
		end
		dz.data.wifi = 0
		logout("wifi")
		if f_logging == "Y" then 
			local millis = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
			dz.log("Temps Wifi : "..millis-begin, dz.LOG_INFO)
		end			
	end
	
	if item.isShellCommandResponse and item.statusCode and item.trigger == 'appel' then
		if f_logging == "Y" then 
			begin = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
		end
		local missedCallList = ""
		local failedCallList = ""
		local succeededCallList = ""
		-- if lbAPIDataCallList.status == nil then
		if not item.ok or not item.isJSON then
			dz.log('Lecture de la CallList Téléphonie impossible', dz.LOG_ERROR)
		else
			callList=item.data
			dz.log('callList : '..callList, dz.LOG_DEBUG)
			local lbAPIDataCallList = dz.utils.fromJSON(callList)
			dz.log('CallList : '..#lbAPIDataCallList.status, dz.LOG_INFO)
			
			if (#lbAPIDataCallList.status>0) then
				contacts = readLuaFromJsonFile(fichier_contacts)
				if contacts == nil then contacts = {} end
				dz.log('Dernier Appel : '..lbAPIDataCallList.status[#lbAPIDataCallList.status].remoteNumber, dz.LOG_INFO)
				dz.log('Dernier Appel : '..traduction(lbAPIDataCallList.status[#lbAPIDataCallList.status].callType), dz.LOG_INFO)
				NumeroEtat = searchName(contacts, lbAPIDataCallList.status[#lbAPIDataCallList.status].remoteNumber) .. " - "..lbAPIDataCallList.status[#lbAPIDataCallList.status].callType
				if DernierAppel and dz.devices(DernierAppel).text ~= traduction(NumeroEtat) then
						dz.devices(DernierAppel).updateText(traduction(NumeroEtat))
				end
				-- x Appels manqués, sans réponse, réussis
				for i, call in ipairs(ReverseTable(lbAPIDataCallList.status)) do
					if call.callType == "missed" and nbMissedCall > 0 then
						--dz.log(call.remoteNumber .. " " .. traduction(call.callType) .. " " .. format_date(call.startTime), dz.LOG_INFO)
						missedCallList = missedCallList .. searchName(contacts, call.remoteNumber) .. " - " .. format_date(call.startTime) .. "\n"
						nbMissedCall = nbMissedCall - 1
					end
					if call.callType == "failed" and nbFailedCall > 0 then
						--dz.log(call.remoteNumber .. " " .. traduction(call.callType) .." ".. format_date(call.startTime), dz.LOG_INFO)
						failedCallList = failedCallList .. searchName(contacts, call.remoteNumber) .." - ".. format_date(call.startTime) .. "\n"
						nbFailedCall = nbFailedCall - 1
					end
					if call.callType == "succeeded" and nbSucceededCall > 0 then
						--dz.log(call.remoteNumber .. " " .. traduction(call.callType) .. " " .. format_date(call.startTime), dz.LOG_INFO)
						succeededCallList = succeededCallList .. searchName(contacts, call.remoteNumber) .. " - " .. format_date(call.startTime) .. "\n"
						nbSucceededCall = nbSucceededCall - 1
					end
				end
				if missedCallList == "" then missedCallList = "Aucun appel à afficher" end
				dz.log('Appels manqués : \n'..missedCallList, dz.LOG_INFO)
				-- Notification appels manqués
				if missedCall and notifyMissedCall == true then
					dz.log("delai depuis la dernière MAJ du device appels manqués : "..tostring(dz.devices(missedCall).lastUpdate.minutesAgo).." minutes", dz.LOG_INFO)
					if dz.devices(missedCall).lastUpdate.minutesAgo < 1 and dz.devices(missedCall).text ~= "Aucun appel à afficher" then 
						   dz.notify("Notification d'appel en absence", "Appel(s) en absence : \n"..tostring(dz.devices(missedCall).text), dz.PRIORITY_NORMAL,dz.SOUND_DEFAULT, "" , notificationTable )
					end
				end

				if missedCall and dz.devices(missedCall).text ~= traduction(missedCallList) then
					dz.devices(missedCall).updateText(traduction(missedCallList))
				end
				if failedCallList == "" then failedCallList = "Aucun appel à afficher" end
				dz.log('Appels sans réponse : \n'..failedCallList, dz.LOG_INFO)
				if failedCall and dz.devices(failedCall).text ~= traduction(failedCallList) then
					dz.devices(failedCall).updateText(traduction(failedCallList))
				end
				if succeededCallList == "" then succeededCallList = "Aucun appel à afficher" end
				dz.log('Appels réussis : \n'..succeededCallList, dz.LOG_INFO)
				if succeededCall and dz.devices(succeededCall).text ~= traduction(succeededCallList) then
					dz.devices(succeededCall).updateText(traduction(succeededCallList))
				end
			else
				NumeroEtat = "Aucun appel à afficher"
				dz.log('Dernier Appel : '..NumeroEtat, dz.LOG_INFO)
				if DernierAppel and dz.devices(DernierAppel).text ~= NumeroEtat then
					dz.devices(DernierAppel).updateText(NumeroEtat)
				end
				if missedCallList == "" then missedCallList = "Aucun appel à afficher" end
				dz.log('Appels manqués : \n'..missedCallList, dz.LOG_INFO)
				if missedCall and dz.devices(missedCall).text ~= traduction(missedCallList) then
					dz.devices(missedCall).updateText(traduction(missedCallList))
				end
				if failedCallList == "" then failedCallList = "Aucun appel à afficher" end
				dz.log('Appels sans réponse : \n'..failedCallList, dz.LOG_INFO)
				if failedCall and dz.devices(failedCall).text ~= traduction(failedCallList) then
					dz.devices(failedCall).updateText(traduction(failedCallList))
				end
				if succeededCallList == "" then succeededCallList = "Aucun appel à afficher" end
				dz.log('Appels réussis : \n'..succeededCallList, dz.LOG_INFO)
				if succeededCall and dz.devices(succeededCall).text ~= traduction(succeededCallList) then
					dz.devices(succeededCall).updateText(traduction(succeededCallList))
				end
			end
		end

		dz.data.appel = 0
		logout("appel")
		if f_logging == "Y" then 
			local millis = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
			dz.log("Temps Appel : "..millis-begin, dz.LOG_INFO)
		end			
	end
	
	if item.isShellCommandResponse and item.statusCode and item.trigger == 'reseau' then
		if f_logging == "Y" then 
			begin = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
		end
		if not item.ok or not item.isJSON then
			dz.log('Lecture de la LAN Réseau impossible', dz.LOG_ERROR)
		else
			LAN = item.data
			LAN=LAN:gsub('"SerialNumber ... ','"SerialNumber" : "'):gsub(" ... ",'     ')
			dz.log('LAN : '..LAN, dz.LOG_DEBUG)
			LAN = dz.utils.fromJSON(LAN)
			-- 20230427 gestion nil
			if LAN ~= nil and LAN.status ~= nil then
			--Version du firmware
				if LAN.status[1].SoftwareVersion and firmware then
					dz.log("Version Firmware : "..LAN.status[1].SoftwareVersion,dz.LOG_INFO)
					if dz.devices(firmware).text ~= LAN.status[1].SoftwareVersion then
						dz.devices(firmware).updateText(LAN.status[1].SoftwareVersion)
					end
				end

			--Uptime
				uptime = LAN.status[1]['Children']
				for l=1,#uptime do -- récupération de l'arbre des périphériques LAN
					if uptime[l]["Key"]== "lan" then
						uptime = uptime[l]
						break
					end
				end
				if uptime.FirstSeen and UptimeLB then
					uptime = delta_date(uptime.FirstSeen)
					dz.log("Uptime : "..uptime,dz.LOG_INFO)
					-- ajout on log une fois par jour
					if dz.devices(UptimeLB).sensorValue ~= dz.utils.stringSplit(uptime,":")[1] then
						if dz.utils.stringSplit(uptime,":")[1] == "" then
							dz.devices(UptimeLB).update(0,0)
						else
							dz.devices(UptimeLB).update(0,dz.utils.stringSplit(uptime,":")[1])
						end
					end
				end

			--Etat du Service TV
				if LAN.status[1].IPTV and ServiceTV then
					dz.log("IPTV : "..tostring(LAN.status[1].IPTV),dz.LOG_INFO)
					if (LAN.status[1].IPTV) then
						dz.devices(ServiceTV).switchOn().checkFirst()
					else
						dz.devices(ServiceTV).switchOff().checkFirst()
					end
				elseif ServiceTV then
					dz.devices(ServiceTV).switchOff().checkFirst()
				end

			--Etat du Service VoIP
				if LAN.status[1].Telephony and VoIP then
					dz.log("Telephony : "..tostring(LAN.status[1].Telephony),dz.LOG_INFO)
					if (LAN.status[1].Telephony) then
						dz.devices(VoIP).switchOn().checkFirst()
					else
						dz.devices(VoIP).switchOff().checkFirst()
					end
				elseif  VoIP then
					dz.devices(VoIP).switchOff().checkFirst()
				end

			--Etat du Service Internet
				if LAN.status[1].Internet and internet then
					dz.log("Internet : "..tostring(LAN.status[1].Internet),dz.LOG_INFO)
					if (LAN.status[1].Internet) then
						dz.devices(internet).switchOn().checkFirst()
					else
						dz.devices(internet).switchOff().checkFirst()
					end
				elseif internet then
						dz.devices(internet).switchOff().checkFirst()
				end

			-- IP WAN
				if LAN.status[1].ConnectionIPv4Address and IPWAN then
					dz.log("IP WAN : "..LAN.status[1].ConnectionIPv4Address,dz.LOG_INFO)
					if  dz.devices(IPWAN).text ~= LAN.status[1].ConnectionIPv4Address then
						dz.devices(IPWAN).updateText(LAN.status[1].ConnectionIPv4Address)
						message="Renouvellement IP"
						if f_notification == "Y" then
							dz.helpers.generalNotify(dz, 'EXPLOIT', scriptName, message, 'telegram')
						end						
					end
				end
			-- IPv6WAN
				if LAN.status[1].ConnectionIPv6Address and IPv6WAN then
					dz.log("IPv6 WAN : "..LAN.status[1].ConnectionIPv6Address,dz.LOG_INFO)
					if  dz.devices(IPv6WAN).text ~= LAN.status[1].ConnectionIPv6Address then
						dz.devices(IPv6WAN).updateText(LAN.status[1].ConnectionIPv6Address)
					end
				end

			--Présence de périphériques
				LAN = LAN.status[1]['Children']
				for l=1,#LAN do -- récupération de l'arbre des périphériques LAN
					if LAN[l]["Key"]== "lan" then
						LAN = LAN[l]['Children']
						break
					end
				end
				
				local k=-1
				for i=1,#devices_livebox_mac_adress do -- recherche de l'adresse MAC et son statut
					for j=1,#LAN do
						if(LAN[j]['DiscoverySource'] == "selflan") then
							k=searchKey(LAN[j]['Children'],devices_livebox_mac_adress[i])
							if (k~=-1 and LAN[j]['Children'][k]['Active']) then
								dz.log('switch : '..LAN[j]['Children'][k]['Name'].." On", dz.LOG_INFO)
								if (dz.devices(LAN[j]['Children'][k]['Name'])) then
									dz.devices(LAN[j]['Children'][k]['Name']).switchOn().checkFirst()
								end
								break
							elseif (k~=-1 and LAN[j]['Children'][k]['Active']==false) then
								dz.log('switch : '..LAN[j]['Children'][k]['Name'].." Off", dz.LOG_INFO)
								if (dz.devices(LAN[j]['Children'][k]['Name'])) then
									dz.devices(LAN[j]['Children'][k]['Name']).switchOff().checkFirst()
								end
								break
							end
						end
					end
					if (k==-1) then
						dz.log('mac : '..devices_livebox_mac_adress[i].." introuvable", dz.LOG_INFO)
					end
				end
			end
		end
		dz.data.reseau = 0
		logout("reseau")	
		if f_logging == "Y" then 
			local millis = dz.helpers.osCommand('date +%s%3N|tr -d "\n"')
			dz.log("Temps Reseau : "..millis-begin, dz.LOG_INFO)
		end		
	end
-- appuie bouton
	if item.isDevice then
	    
		--Connexion et récupération du cookies
        os.execute("curl -s -o \""..OutputA.."\" -X POST -c \""..CookiesA.."\" -H 'Content-Type: application/x-sah-ws-4-call+json' -H 'Authorization: X-Sah-Login' -d \"{\\\"service\\\":\\\"sah.Device.Information\\\",\\\"method\\\":\\\"createContext\\\",\\\"parameters\\\":{\\\"applicationName\\\":\\\"so_sdkut\\\",\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\""..password.."\\\"}}\" http://"..adresseLB.."/ws > /dev/null")
        --Lecture du cookies pour utilisation ultérieure
        myContextID = os.capture("tail -n1 \""..OutputA.."\" | sed 's/{\"status\":0,\"data\":{\"contextID\":\"//1'| sed 's/\",//1' | sed 's/\"groups\":\"http,admin//1' | sed 's/\"}}//1'")
        dz.log('Context : '..myContextID, dz.LOG_DEBUG)
		
		if(item.name == wifi5) then
			if liveBox3 then chip='wifi1_ath' else chip='wifi0_quan' end
			os.execute("curl -m1 -s -b \""..CookiesA.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..
				myContextID.."\" -d \"{\\\"service\\\":\\\"NeMo.Intf.lan\\\",\\\"method\\\":\\\"setWLANConfig\\\",\\\"parameters\\\":{\\\"mibs\\\":{\\\"penable\\\":{\\\""..chip.."\\\":{\\\"PersistentEnable\\\":"..
				tostring(item.active)..", \\\"Enable\\\":true}}}}}\" http://"..adresseLB.."/ws")
			dz.log("wifi5 "..tostring(item.active),dz.LOG_INFO)
		elseif(item.name == wifi24) then
			if liveBox3 then chip='wifi0_ath' else chip='wifi0_bcm' end
			os.execute("curl -m1 -s -b \""..CookiesA.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..
				myContextID.."\" -d \"{\\\"service\\\":\\\"NeMo.Intf.lan\\\",\\\"method\\\":\\\"setWLANConfig\\\",\\\"parameters\\\":{\\\"mibs\\\":{\\\"penable\\\":{\\\""..chip.."\\\":{\\\"PersistentEnable\\\":"..
				tostring(item.active)..", \\\"Enable\\\":true}}}}}\" http://"..adresseLB.."/ws")
			dz.log("wifi24 "..tostring(item.active),dz.LOG_INFO)
		elseif(item.name == clearCallList) then
			os.execute("curl -m1 -s -b \""..CookiesA.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..
				myContextID.."\" -d \"{\\\"service\\\":\\\"VoiceService.VoiceApplication\\\",\\\"method\\\":\\\"clearCallList\\\",\\\"parameters\\\":{}}\" http://"..adresseLB.."/ws")
			dz.log("clearCallList "..tostring(item.active),dz.LOG_INFO)
		elseif(item.name == reboot) then
			dz.devices(internet).switchOff()
			os.execute("curl -m1 -s -b \""..CookiesA.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..
				myContextID.."\" -d \"{\\\"parameters\\\":{}}\" http://"..adresseLB.."/sysbus/NMC:reboot")
			dz.log("reboot "..tostring(item.active),dz.LOG_INFO)
		elseif(item.name == sonner) then
			os.execute("curl -m1 -s -b \""..CookiesA.."\" -X POST -H 'Content-Type: application/x-sah-ws-4-call+json' -H \"X-Context: "..
				myContextID.."\" -d \"{\\\"parameters\\\":{}}\" http://"..adresseLB.."/sysbus/VoiceService/VoiceApplication:ring")
			dz.log("sonner "..tostring(item.active),dz.LOG_INFO)
		end
		--Déconnexion et suppression des fichiers temporaires
		os.execute("curl -m1 -s -b "..CookiesA.." -X POST http://"..adresseLB.."/logout")
		os.execute('rm "'..CookiesA..'" "'..OutputA..'"')
	end
end -- execute
} -- return

Re: [DzVents] LiveBox 3 et 4

Publié : 21 oct. 2024, 20:39
par salinois
hello,
merci Pierrotori,

je vais monter de nouveau un RPi de test pour le tester.
a plus

salinois

Re: [DzVents] LiveBox 3 et 4

Publié : 08 nov. 2024, 21:03
par salinois
hello Pierrotori,

j'ai mis ton script pour ma livebox5, et ça marche
là, j'avais noté comment configurer, c'est pas comme "Couleur Tempo" où je n'arrive pas.

En tous les cas , beau travail. merci encore à toi.

salinois

Re: [DzVents] LiveBox 3 et 4

Publié : 18 nov. 2024, 21:16
par pierrotori
merci en effet ça tourne bien
c’est quoi ton couleur tempo?

Re: [DzVents] LiveBox 3 et 4

Publié : 19 nov. 2024, 13:07
par Keros
C'est un autre script dont il parle déjà dans un autre sujet. On va éviter d'en parler également ici ;)

Re: [DzVents] LiveBox 3 et 4

Publié : 23 nov. 2024, 14:16
par salinois
salinois a écrit : 08 nov. 2024, 21:03 hello Pierrotori,

j'ai mis ton script pour ma livebox5, et ça marche
là, j'avais noté comment configurer, c'est pas comme "Couleur Tempo" où je n'arrive pas.

En tous les cas , beau travail. merci encore à toi.

salinois
c'est vrai , on mélange pas, tout va bien sur ton script.

salinois