[DzVents] LiveBox 3 et 4

Vous avez créé un script LUA dont vous êtes fier, un .sh génial, un programme Python hors du commun, un Tuto, c'est ici que vous pouvez les partager.
pierrotori
Messages : 821
Inscription : 29 févr. 2016, 12:11

Re: [DzVents] LiveBox 3 et 4

Message 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
salinois
Messages : 330
Inscription : 08 févr. 2024, 19:10

Re: [DzVents] LiveBox 3 et 4

Message par salinois »

hello,
merci Pierrotori,

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

salinois
salinois
Messages : 330
Inscription : 08 févr. 2024, 19:10

Re: [DzVents] LiveBox 3 et 4

Message 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
pierrotori
Messages : 821
Inscription : 29 févr. 2016, 12:11

Re: [DzVents] LiveBox 3 et 4

Message par pierrotori »

merci en effet ça tourne bien
c’est quoi ton couleur tempo?
Keros
Messages : 6638
Inscription : 23 juil. 2019, 20:57

Re: [DzVents] LiveBox 3 et 4

Message par Keros »

C'est un autre script dont il parle déjà dans un autre sujet. On va éviter d'en parler également ici ;)
Comment bien utiliser le forum : Poser une question, Mettre un script, un fichier, une image ou des logs
Mes petits guides : Débuter en programmation, Le débogage, Le choix de matériel, Les sauvegardes
Ma présentation - Mes Tutos
salinois
Messages : 330
Inscription : 08 févr. 2024, 19:10

Re: [DzVents] LiveBox 3 et 4

Message 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
Répondre