[LUA] Durée de trajet avec Waze

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.
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: [LUA] Durée de trajet avec Waze

Message par garycooper »

Ok, merci de la précision. Par contre, en mettant le jour en toute lettres, impossible pour moi de faire marcher le script. J'ai essayé en minuscules, avec guillemets, sans guillemets ... Rien n'y fait. L'essentiel c'est que j'arrive maintenant à le déclencher comme je veux 😎
jjlf
Messages : 43
Inscription : 04 févr. 2018, 20:58

Re: [LUA] Durée de trajet avec Waze

Message par jjlf »

Il semble que la structure des requêtes a encore changé depuis ce matin.
Ils sont revenus sur l'ancienne representation json :

jsonTrajet['response']['routeName']
<->
jsonTrajet['response'][1]['route_name']

jsonTrajet['response']['results']
<->
jsonTrajet['response'][1]['result']

jsonTrajet['response']['streetNames']
<->
jsonTrajet['response'][1]['street_name']

results['crossTime']
<->
results['cross_time']
Chrominator
Messages : 1042
Inscription : 19 déc. 2015, 07:29
Localisation : France

Re: [LUA] Durée de trajet avec Waze

Message par Chrominator »

En effet, ça a dû changer après 9h car le calcul a fonctionné chez moi ce matin.

Est-ce que Waze veut limiter le trafic et l'utilisation de ces requêtes ? :?

Pas d'autre choix que de gérer des versions, au cas où ça change encore...

Je suis pas expert, mais j'ai adopté le principe suivant ;
Si l'une des clés json considérée comme actuelle est trouvée, on utilise dans tout le script cette forme, sinon on revient à la précédente.
Pour tester sans provoquer l'interception d'une erreur en lua, on utilise pcall() qui va nous indiquer si l'exécution s'est bien passée ou pas.

Ça donne un script un peu lourd mais ça fonctionne.

Code : Tout sélectionner

---------------------------------
-- Script de calcul de temps pour un trajet entre 2 coordonnées
-- Auteur : Neutrino
-- Date : 7 septembre 2015
-- Nécessite un capteur virtuel de type Text
-- source :
-- http://www.domo-blog.fr/info-trajet-waze-eedomus-version-raspberry/
---------------------------------
-- Modif Chrominator 
--
-- 	2016-01-30 : 	Remplacement des secondes du trajet par " mn"
--					Pas de détermination du temps de trajet les W-E et jours fériés
--	2017-11-11 : 	Détermination du nom des routes principales (les plus longtemps parcourues) car routeName n'existe plus dans le JSON
--
--	2021-11-10 : 	Mise à jour consécutive à des changements dans l'API (result, cross_time, street_name)
--					Ajout d'un custom sensor représentant la durée en heures/minutes
--
--  2021-12-08 :	Retour à l'ancienne forme du json par Waze - Adaptation en fonction de la version identifiée et à l'aide de pcall()
--

DEBUG=true
local RUN=true

function voir_les_logs (s) -- nécessite la variable DEBUG
    if DEBUG then
      if s ~= nil then
        print (s)
      else
        print ("aucune valeur affichable")
      end
    end
end

commandArray={}

if RUN == false then return commandArray end

--import des fontions pour lire le JSON
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
--variables à modifier----------------
--idx du capteur
idx = '1051'				-- Capteur de type texte pour afficher la durée du trajet et le nom de la principale route empruntée.
idx_curve = '1052'			-- Capteur de type voltmetre pour archiver les temps de parcours calculés
idx_duree = '1061'			-- Affiche un graphique en heure/minutes
-- y = latitude et x = longitude
--coordonnées de départ
departx="2.2944990547869546"-- Tour Eiffel à Paris
departy="48.85859381443764"
--coordonnées d'arrivée		-- Mairie de Paris
arrivex="2.3414642913399804"
arrivey="48.86416325734324"
---récupère l'heure actuelle en minutes
time=os.time()
minutes=tonumber(os.date('%M',time))
hours=tonumber(os.date('%H',time))
maintenant=tonumber(hours*60+minutes)

-- Récupère le jour pour ne pas calculer de trajet les week-end.
-- Sunday = 0 - Saturday = 6
local weekday = os.date('%w')

---calcule du trajet entre 17h00 et 17h15
if (maintenant>=1020 and maintenant<= 1035 and weekday == 5) or DEBUG then

	-----------------------------------------
	----------------------------------------------------------------
	--Récupération du trajet et de sa durée en temps réel via WAZE--
	----------------------------------------------------------------
	voir_les_logs('curl --referer https://www.waze.com "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A'..departx..'+y%3A'..departy..'&to=x%3A'..arrivex..'+y%3A'..arrivey..'&returnJSON=true&returnGeometries=true&returnInstructions=true&timeout=60000&nPaths=1&clientVersion=4.0.0&options=AVOID_TRAILS%3At%2CALLOW_UTURNS%3At%2CAVOID_TOLL_ROADS"')
	local waze=assert(io.popen('curl --referer https://www.waze.com "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A'..departx..'+y%3A'..departy..'&to=x%3A'..arrivex..'+y%3A'..arrivey..'&returnJSON=true&timeout=60000&clientVersion=4.0.0&options=AVOID_TRAILS%3At%2CALLOW_UTURNS"'))
	local infowaze = waze:read('*all')
	waze:close()
	local jsonTrajet = json:decode(infowaze)
	-- identification de la version de l'API Waze
	if pcall(function () routeName = jsonTrajet['response'][1]['route_name'] end) then 
		version_id=1 
		voir_les_logs("Version Waze #1 identifiée - nouvelle version de novembre 2021")
	else 
		version_id=0 
		voir_les_logs("Version Waze #0 identifiée - Ancienne version antérieure à novembre 2021")
		end
	--Noms des principales routes empruntées
	if version_id == 1 then routeName = jsonTrajet['response'][1]['route_name'] else routeName = jsonTrajet['response']['routeName'] end
	if routeName == nil then routeName="route non précisée" end
	voir_les_logs("RouteName="..routeName)
	--Liste des routes empruntées
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	--Temps de trajet en secondes
	routeTotalTimeSec = 0
	--calcul du temps de trajet
	for response,results in pairs(route) do
		if version_id == 1 then routeTotalTimeSec = routeTotalTimeSec + results['cross_time'] else routeTotalTimeSec = routeTotalTimeSec + results['crossTime'] end
	end
	
	--Temps de trajet en minutes
	routeTotalTimeMin = routeTotalTimeSec/60-((routeTotalTimeSec%60)/60)

	-- Détermination des noms des routes employées
	xtime = {}
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	if version_id == 1 then voie = jsonTrajet['response'][1]['street_name'] else voie = jsonTrajet['response']['streetNames'] end
	for response,results in pairs(route) do
		i = tonumber(results['street'])
		if voie[i] == nil then voie[i] = "/ND" end
		if xtime[i]==nil then xtime[i]=0 end
		if version_id == 1 then xtime[i]=xtime[i]+tonumber(results['cross_time']) else xtime[i]=xtime[i]+tonumber(results['crossTime']) end
--[[
		if version_id == 1 then 
			voir_les_logs(tostring(response).." "..results['cross_time'].." "..results['street'].." "..voie[i].." "..xtime[i])
		else
			voir_les_logs(tostring(response).." "..results['crossTime'].." "..results['street'].." "..voie[i].." "..xtime[i])
		end
--]]
	end

	i=0
	j=1
	chemin = {}
	trajet = {}

	-- Détermination des durées de parcours pour chacune des routes
	
	for street in pairs(voie) do
		if xtime[street] ~= nil then
			upd=0
			for i in ipairs(chemin) do
				if chemin[i]==voie[street] then
					trajet[i]=trajet[i]+xtime[street]
					upd=1
				end
			end
			if upd == 0 and xtime[street]~=nil and voie[street]~=nil then 
				voir_les_logs("voie[street]="..voie[street])
				voir_les_logs("xtime[street]="..xtime[street])
				voir_les_logs("j="..j)
				chemin[j]=voie[street]
				if xtime[street]~=nil then
					trajet[j]=xtime[street]
				else
					trajet[j]=0
				end
				voir_les_logs("chemin["..tostring(j).."]="..chemin[j])
				voir_les_logs("trajet["..tostring(j).."]="..trajet[j])
				j=j+1
			end
		end
	end
	voie4T=0
	voie5T=0

	-- Recherche de deux routes les plus utilisées
	
	for i in ipairs(chemin) do
		voir_les_logs("chemin["..tostring(i).."]="..chemin[i])
		voir_les_logs("trajet["..tostring(i).."]="..trajet[i])
		if trajet[i]~=nil and chemin[i]~="/ND" then
			if trajet[i] > voie4T then 
				voie4N=chemin[i]
				voie4T=trajet[i]
			elseif trajet[i] > voie5T then 
				voie5N=chemin[i]
				voie5T=trajet[i]
			end
		end
	end
	voir_les_logs(voie4N.." "..voie5N)
	routeName=voie4N.." "..voie5N
	routeTotalTime = os.date("%H:%M", routeTotalTimeSec-3600)..'&nbsppar&nbsp '..string.gsub(routeName, ' ', '&nbsp')
	commandArray[#commandArray+1]={['UpdateDevice'] =idx..'|0|' .. tostring(routeTotalTime)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_curve..'|0|' .. tostring(routeTotalTimeMin)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_duree..'|0|' .. tostring(os.date("%H.%M", routeTotalTimeSec-3600))}
	commandArray['Variable:Trajet-retour'] = tostring(routeTotalTimeMin)
end
return commandArray
Trajet de la tour Eiffel à la mairie de Paris :
Screenshot 2021-12-08 at 05-00-53 Domoticz_dev.png
Screenshot 2021-12-08 at 05-00-53 Domoticz_dev.png (33.67 Kio) Consulté 3458 fois
Un bon frein vaut mieux que deux sparadraps.

Ubuntu 24.04.3 LTS - Domoticz 2025.1 (build 16782)
Pentium G3220T 2.6GHz - 4Go DDR3
RFXtrx433 USB Ver Pro1/1043
Z-Stick GEN5 Version: 1.6-1136-g07ea22bb
Rtl433 RTL-SDR receiver
RFLink Gateway
Zigbee SLZB-06
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: [LUA] Durée de trajet avec Waze

Message par garycooper »

Hello ! Merci pour l'alerte et le travail. Avec le script corrigé, j'ai à nouveau l'erreur disant qu'il y a trop de lignes :
2021-12-08 11:12:02.752 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_waze_aller.lua: /home/pi/domoticz/scripts/lua/JSON.lua:1348: /home/pi/domoticz/scripts/lua/JSON.lua:1171: Lua script execution exceeds maximum number of lines
Ca concerne un trajet d'environ 2h à 2h30 selon les conditions météo
Chrominator
Messages : 1042
Inscription : 19 déc. 2015, 07:29
Localisation : France

Re: [LUA] Durée de trajet avec Waze

Message par Chrominator »

Oui, même en limitant le nombre de lignes en sortie les trajets un peu longs font planter le décodage par JSON.lua.
Il faudrait que tu jettes un oeil du côté de WazeRouteCalculator, il a l'air prometteur je ne l'ai pas testé.

J'ai ajouté des options dans le script, ça peut servir ; possible de spécifier quels contournements on souhaite (chemins, demi-tours, péages, ferries) et si on utilise autre chose qu'une voiture (taxi ou moto).

Code : Tout sélectionner

---------------------------------
-- Script de calcul de temps pour un trajet entre 2 coordonnées
-- Auteur : Neutrino
-- Date : 7 septembre 2015
-- Nécessite un capteur virtuel de type Text
-- source :
-- http://www.domo-blog.fr/info-trajet-waze-eedomus-version-raspberry/
---------------------------------
-- Modif Chrominator 
--
-- 	2016-01-30 : 	Remplacement des secondes du trajet par " mn"
--					Pas de détermination du temps de trajet les W-E et jours fériés
--	2017-11-11 : 	Détermination du nom des routes principales (les plus longtemps parcourues) car routeName n'existe plus dans le JSON
--
--	2021-11-10 : 	Mise à jour consécutive à des changements dans l'API (result, cross_time, street_name)
--					Ajout d'un custom sensor représentant la durée en heures/minutes
--
--  2021-12-08 :	Retour à l'ancienne forme du json par Waze - Adaptation en fonction de la version identifiée et à l'aide de pcall()
--					Ajout de critères de contournement (chemins, demi-tours, péages, ferries) et du type de véhicule utilisé (defaut Voiture, alternative TAXI ou MOTORBIKE)
--

DEBUG=false
local RUN=true

function voir_les_logs (s) -- nécessite la variable DEBUG
    if DEBUG then
      if s ~= nil then
        print (s)
      else
        print ("aucune valeur affichable")
      end
    end
end

commandArray={}

if RUN == false then return commandArray end

--import des fontions pour lire le JSON
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
--variables à modifier----------------
--idx du capteur
idx = '1051'				-- Capteur de type texte pour afficher la durée du trajet et le nom de la principale route empruntée.
idx_curve = '1052'			-- Capteur de type voltmetre pour archiver les temps de parcours calculés
idx_duree = '1061'			-- Affiche un graphique en heure/minutes
-- y = latitude et x = longitude
--coordonnées de départ
--departx="3.0708952519782207"	-- Mairie de Lille
--departy="50.633567983718045"
departx="2.2944990547869546"-- Tour Eiffel à Paris
departy="48.85859381443764"
--coordonnées d'arrivée		
--arrivex="7.502630192573109"		-- Mairie de Menton
--arrivey="43.775770187431625"

arrivex="2.3414642913399804"	-- Mairie de Paris
arrivey="48.86416325734324"

---récupère l'heure actuelle en minutes
time=os.time()
minutes=tonumber(os.date('%M',time))
hours=tonumber(os.date('%H',time))
maintenant=tonumber(hours*60+minutes)

-- options pour l'API Waze
-- Mettre la valeur à true ou false en fonction de ce que vous voulez

local waze_options = {
	["AVOID_TRAILS"] = true,				-- Eviter les chemins
	["ALLOW_UTURNS"] = false,				-- Eviter les demi-tours
	["AVOID_TOLL_ROADS"] = false,			-- Eviter les routes à péage
	["AVOID_FERRIES"] = true				-- Eviter les ferries
	}

local vehicleType = {						-- Un seul choix à true - si tous à false = voiture
	["MOTORCYCLE"] = false,
	["TAXI"] = false					
	}
	
local subscription = "*"					-- CRIT'AIR - A déterminer ce qu'il faut indiquer si on a pas de vignette CRIT'AIR

-- Récupère le jour pour ne pas calculer de trajet les week-end.
-- Sunday = 0 - Saturday = 6
local weekday = os.date('%w')

---calcule du trajet entre 17h00 et 17h15
if (maintenant>=1020 and maintenant<= 1035 and weekday == 5) or DEBUG then

	-----------------------------------------
	----------------------------------------------------------------
	--Récupération du trajet et de sa durée en temps réel via WAZE--
	----------------------------------------------------------------
	-- Préparation de l'url
	url = "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A"..departx.."+y%3A"..departy.."&to=x%3A"..arrivex.."+y%3A"..arrivey.."&returnJSON=true&timeout=60000&nPaths=1&clientVersion=4.0.0&subscription=" .. tostring(subscription)
	-- vérification des options
	local option_list = ""
	for option in pairs(waze_options) do
		if waze_options[option] then option_list = option_list .. option .. "&" end
	end
	local vehicule = ""
	for option in pairs(vehicleType) do
		if vehicleType[option] then option_list = option_list .. "vehicleType=" .. option .. "&" end
	end
	-- supprime le & supplémentaire
	option_list = option_list:sub(1, -2)
--	voir_les_logs('curl --referer https://www.waze.com "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A'..departx..'+y%3A'..departy..'&to=x%3A'..arrivex..'+y%3A'..arrivey..'&returnJSON=true&returnGeometries=true&returnInstructions=true&vehicleType=MOTORCYCLE&timeout=60000&nPaths=1&clientVersion=4.0.0&options=AVOID_TRAILS%3At%2CALLOW_UTURNS%3At%2CAVOID_TOLL_ROADS"')
	voir_les_logs('curl --referer https://www.waze.com '.. '"' .. url .. '&options=' .. option_list..'"')
	local waze=assert(io.popen('curl --referer https://www.waze.com '.. '"' .. url .. '&options=' .. option_list..'"'))
	--if AVOID_TRAILS then 
	local infowaze = waze:read('*all')
	waze:close()
	local version_id = nil
	local jsonTrajet = json:decode(infowaze)
	-- identification de la version de l'API Waze
	if pcall(function () routeName = jsonTrajet['response'][1]['route_name'] end) then 
		version_id=1 
		print("Version Waze #1 identifiée - nouvelle version de novembre 2021")
	end
	if pcall(function () routeName = jsonTrajet['response']['route_name'] end) then 
		version_id=0 
		print("Version Waze #0 identifiée - Ancienne version antérieure à novembre 2021")
	end
	if version_id == nil then print("Version Waze non reconnue ou trajet trop long - Sortie") return commandArray end
	--Noms des principales routes empruntées
	if version_id == 1 then routeName = jsonTrajet['response'][1]['route_name'] else routeName = jsonTrajet['response']['routeName'] end
	if routeName == nil then routeName="route non précisée" end
	voir_les_logs("RouteName="..routeName)
	--Liste des routes empruntées
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	--Temps de trajet en secondes
	routeTotalTimeSec = 0
	--calcul du temps de trajet
	for response,results in pairs(route) do
		if version_id == 1 then routeTotalTimeSec = routeTotalTimeSec + results['cross_time'] else routeTotalTimeSec = routeTotalTimeSec + results['crossTime'] end
	end
	
	--Temps de trajet en minutes
	routeTotalTimeMin = routeTotalTimeSec/60-((routeTotalTimeSec%60)/60)

	-- Détermination des noms des routes employées
	xtime = {}
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	if version_id == 1 then voie = jsonTrajet['response'][1]['street_name'] else voie = jsonTrajet['response']['streetNames'] end
	for response,results in pairs(route) do
		i = tonumber(results['street'])
		if voie[i] == nil then voie[i] = "/ND" end
		if xtime[i]==nil then xtime[i]=0 end
		if version_id == 1 then xtime[i]=xtime[i]+tonumber(results['cross_time']) else xtime[i]=xtime[i]+tonumber(results['crossTime']) end
--[[
		if version_id == 1 then 
			voir_les_logs(tostring(response).." "..results['cross_time'].." "..results['street'].." "..voie[i].." "..xtime[i])
		else
			voir_les_logs(tostring(response).." "..results['crossTime'].." "..results['street'].." "..voie[i].." "..xtime[i])
		end
--]]
	end

	i=0
	j=1
	chemin = {}
	trajet = {}

	-- Détermination des durées de parcours pour chacune des routes
	
	for street in pairs(voie) do
		if xtime[street] ~= nil then
			upd=0
			for i in ipairs(chemin) do
				if chemin[i]==voie[street] then
					trajet[i]=trajet[i]+xtime[street]
					upd=1
				end
			end
			if upd == 0 and xtime[street]~=nil and voie[street]~=nil then 
				voir_les_logs("voie[street]="..voie[street])
				voir_les_logs("xtime[street]="..xtime[street])
				voir_les_logs("j="..j)
				chemin[j]=voie[street]
				if xtime[street]~=nil then
					trajet[j]=xtime[street]
				else
					trajet[j]=0
				end
				voir_les_logs("chemin["..tostring(j).."]="..chemin[j])
				voir_les_logs("trajet["..tostring(j).."]="..trajet[j])
				j=j+1
			end
		end
	end
	voie4T=0
	voie5T=0

	-- Recherche de deux routes les plus utilisées
	
	for i in ipairs(chemin) do
		voir_les_logs("chemin["..tostring(i).."]="..chemin[i])
		voir_les_logs("trajet["..tostring(i).."]="..trajet[i])
		if trajet[i]~=nil and chemin[i]~="/ND" then
			if trajet[i] > voie4T then 
				voie4N=chemin[i]
				voie4T=trajet[i]
			elseif trajet[i] > voie5T then 
				voie5N=chemin[i]
				voie5T=trajet[i]
			end
		end
	end
	voir_les_logs(voie4N.." "..voie5N)
	routeName=voie4N.." "..voie5N
	routeTotalTime = os.date("%H:%M", routeTotalTimeSec-3600)..'&nbsppar&nbsp '..string.gsub(routeName, ' ', '&nbsp')
	commandArray[#commandArray+1]={['UpdateDevice'] =idx..'|0|' .. tostring(routeTotalTime)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_curve..'|0|' .. tostring(routeTotalTimeMin)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_duree..'|0|' .. tostring(os.date("%H.%M", routeTotalTimeSec-3600))}
	commandArray['Variable:Trajet-retour'] = tostring(routeTotalTimeMin)
end
return commandArray
Un bon frein vaut mieux que deux sparadraps.

Ubuntu 24.04.3 LTS - Domoticz 2025.1 (build 16782)
Pentium G3220T 2.6GHz - 4Go DDR3
RFXtrx433 USB Ver Pro1/1043
Z-Stick GEN5 Version: 1.6-1136-g07ea22bb
Rtl433 RTL-SDR receiver
RFLink Gateway
Zigbee SLZB-06
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: [LUA] Durée de trajet avec Waze

Message par garycooper »

Sympas les options ajoutées ! J'ai testé sur mon trajet quotidien (environ 25 à 30min) et ça fonctionne parfaitement. Par contre sur mon trajet souhaité (1h50) je suis toujours planté à cause du nombre de lignes. J'ai tenté en mettant l'arrivée au centre su village mais ça ne change rien malheureusement. Bizarre parce qu'avant le changement de "langage", je n'avais pas de problème pour exécuter le script.
Chrominator
Messages : 1042
Inscription : 19 déc. 2015, 07:29
Localisation : France

Re: [LUA] Durée de trajet avec Waze

Message par Chrominator »

Allez, un dernier jet qui fonctionne de Marseille à Menton (4:30) par exemple.
Pour Lille/Menton l'API Waze se plante et renvoie un "internal error".

Petit ajout du mode de transport dans le widget. ;)
Screenshot 2021-12-09 at 08-05-53 Domoticz_dev.png
Screenshot 2021-12-09 at 08-05-53 Domoticz_dev.png (17.52 Kio) Consulté 3360 fois
Ça devrait dépanner la plupart d'entre nous.

Code : Tout sélectionner

---------------------------------
-- Script de calcul de temps pour un trajet entre 2 coordonnées
-- Auteur : Neutrino
-- Date : 7 septembre 2015
-- Nécessite un capteur virtuel de type Text
-- source :
-- http://www.domo-blog.fr/info-trajet-waze-eedomus-version-raspberry/
---------------------------------
-- Modif Chrominator 
--
-- 	2016-01-30 : 	Remplacement des secondes du trajet par " mn"
--					Pas de détermination du temps de trajet les W-E et jours fériés
--	2017-11-11 : 	Détermination du nom des routes principales (les plus longtemps parcourues) car routeName n'existe plus dans le JSON
--
--	2021-11-10 : 	Mise à jour consécutive à des changements dans l'API (result, cross_time, street_name)
--					Ajout d'un custom sensor représentant la durée en heures/minutes
--
--  2021-12-08 :	Retour à l'ancienne forme du json par Waze - Adaptation en fonction de la version identifiée et à l'aide de pcall()
--					Ajout de critères de contournement (chemins, demi-tours, péages, ferries) et du type de véhicule utilisé (defaut Voiture, alternative TAXI ou MOTORBIKE)
--					Suppression des lignes de réponse json inutiles pour le calcul de la durée de trajet
--

DEBUG=false
local RUN=true

function voir_les_logs (s) -- nécessite la variable DEBUG
    if DEBUG then
      if s ~= nil then
        print (s)
      else
        print ("aucune valeur affichable")
      end
    end
end

commandArray={}

if RUN == false then return commandArray end

--import des fontions pour lire le JSON
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()

--variables à modifier----------------
--idx du capteur
idx = '1051'				-- Capteur de type texte pour afficher la durée du trajet et le nom de la principale route empruntée.
idx_curve = '1052'			-- Capteur de type voltmetre pour archiver les temps de parcours calculés
idx_duree = '1061'			-- Affiche un graphique en heure/minutes
-- y = latitude et x = longitude
--coordonnées de départ
departx="5.364967"	-- Mairie de Marseille
departy="43.304719"

--departx="2.2944990547869546"-- Tour Eiffel à Paris
--departy="48.85859381443764"
--coordonnées d'arrivée		
arrivex="7.507769"		-- Mairie de Menton
arrivey="43.77783"

--arrivex="2.341464"	-- Mairie de Paris
--arrivey="48.86416"

---récupère l'heure actuelle en minutes
time=os.time()
minutes=tonumber(os.date('%M',time))
hours=tonumber(os.date('%H',time))
maintenant=tonumber(hours*60+minutes)

-- options pour l'API Waze
-- Mettre la valeur à true ou false en fonction de ce que vous voulez

local waze_options = {
	["AVOID_TRAILS"] = true,				-- Eviter les chemins
	["ALLOW_UTURNS"] = false,				-- Autoriser les demi-tours
	["AVOID_TOLL_ROADS"] = true,			-- Eviter les routes à péage
	["AVOID_FERRIES"] = true				-- Eviter les ferries
	}

local vehicleType = {						-- Un seul choix à true - si tous à false = voiture
	["MOTORCYCLE"] = false,
	["TAXI"] = false					
	}
	
local subscription = "*"					-- CRIT'AIR - A déterminer ce qu'il faut indiquer si on a pas de vignette CRIT'AIR

local useless_keys = {
	'"altStreets":null,',
	'"tiles":null,',
	'"clientIds":null,',
	'"laneType":null,',
	'"areas":null,',
	'"requiredPermits":null,',
	'"clientLaneSet":null,',
	'"roadSign":null,',
	'"detour":null,',
	'"naiveRoute":null,',
	'"detourSavingsNoRt":null,',
	'"detourRoute":null,',
	'"naiveRouteFullResult",:null',
	'"detourRouteFullResult":null,',
	'"instruction":null,',
	'"additionalInstruction":null,',
	'"knownDirection":true,',
	'"penalty":[0-9],',
	'"roadType":[0-9],',
	'"isToll":false,',
	'"useHovLane":false,',
	'"attributes":[0-9],',
	'"lane":"WHOLE_SEGMENT",',
	'"avoidStatus":"OPEN",',
	'"isInvalid":false,',
	'"isBlocked":false,',
	'"detourSavings":[0-9],',
    '"mergeOffset":[0-9],'
	}

--[[
On dégrossi le résultat qui est trop gros parfois pour Domoticz
--]]

function remove_garbage(json_string, garbage)
	infowaze, nb = string.gsub(json_string, garbage, "")
	return infowaze
end
	
-- Récupère le jour pour ne pas calculer de trajet les week-end.
-- Sunday = 0 - Saturday = 6
local weekday = os.date('%w')

---calcule du trajet entre 17h00 et 17h15
if (maintenant>=1020 and maintenant<= 1035 and weekday == 5) or DEBUG then

	-----------------------------------------
	----------------------------------------------------------------
	--Récupération du trajet et de sa durée en temps réel via WAZE--
	----------------------------------------------------------------
	-- Préparation de l'url
	url = "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A"..departx.."+y%3A"..departy.."&to=x%3A"..arrivex.."+y%3A"..arrivey.."&returnJSON=true&timeout=60000&nPaths=1&clientVersion=4.0.0&subscription=" .. tostring(subscription)

	-- vérification des options
	local option_list = ""
	for option in pairs(waze_options) do
		if waze_options[option] then option_list = option_list .. option .. "&" end
	end
	local vehicule = ""
	for option in pairs(vehicleType) do
		if vehicleType[option] then option_list = option_list .. "vehicleType=" .. option .. "&" end
	end
	-- supprime le & supplémentaire
	option_list = option_list:sub(1, -2)
--	voir_les_logs('curl --referer https://www.waze.com "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A'..departx..'+y%3A'..departy..'&to=x%3A'..arrivex..'+y%3A'..arrivey..'&returnJSON=true&returnGeometries=true&returnInstructions=true&vehicleType=MOTORCYCLE&timeout=60000&nPaths=1&clientVersion=4.0.0&options=AVOID_TRAILS%3At%2CALLOW_UTURNS%3At%2CAVOID_TOLL_ROADS"')
	voir_les_logs('curl --referer https://www.waze.com '.. '"' .. url .. '&options=' .. option_list..'"')
	local waze=assert(io.popen('curl --referer https://www.waze.com '.. '"' .. url .. '&options=' .. option_list..'"'))
	local infowaze = waze:read('*all')
	waze:close()
	for index in pairs(useless_keys) do
		infowaze = remove_garbage(infowaze, useless_keys[index])
	end
	local version_id = nil
	local jsonTrajet = json:decode(infowaze)
	-- identification de la version de l'API Waze
	if pcall(function () routeName = jsonTrajet['response'][1]['route_name'] end) then 
		version_id=1 
		print("Version Waze #1 identifiée - nouvelle version de novembre 2021")
	end
	if pcall(function () routeName = jsonTrajet['response']['route_name'] end) then 
		version_id=0 
		print("Version Waze #0 identifiée - Ancienne version antérieure à novembre 2021")
	end
	if version_id == nil then print("Version Waze non reconnue ou trajet trop long - Sortie") return commandArray end
	--Noms des principales routes empruntées
	if version_id == 1 then routeName = jsonTrajet['response'][1]['route_name'] else routeName = jsonTrajet['response']['routeName'] end
	if routeName == nil then routeName="route non précisée" end
	voir_les_logs("RouteName="..routeName)
	--Liste des routes empruntées
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	--Temps de trajet en secondes
	routeTotalTimeSec = 0
	--calcul du temps de trajet
	for response,results in pairs(route) do
		if version_id == 1 then routeTotalTimeSec = routeTotalTimeSec + results['cross_time'] else routeTotalTimeSec = routeTotalTimeSec + results['crossTime'] end
	end
	
	--Temps de trajet en minutes
	routeTotalTimeMin = routeTotalTimeSec/60-((routeTotalTimeSec%60)/60)

	-- Détermination des noms des routes employées
	xtime = {}
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	if version_id == 1 then voie = jsonTrajet['response'][1]['street_name'] else voie = jsonTrajet['response']['streetNames'] end
	for response,results in pairs(route) do
		i = tonumber(results['street'])
		if voie[i] == nil then voie[i] = "/ND" end
		if xtime[i]==nil then xtime[i]=0 end
		if version_id == 1 then xtime[i]=xtime[i]+tonumber(results['cross_time']) else xtime[i]=xtime[i]+tonumber(results['crossTime']) end
--[[
		if version_id == 1 then 
			voir_les_logs(tostring(response).." "..results['cross_time'].." "..results['street'].." "..voie[i].." "..xtime[i])
		else
			voir_les_logs(tostring(response).." "..results['crossTime'].." "..results['street'].." "..voie[i].." "..xtime[i])
		end
--]]
	end

	i=0
	j=1
	chemin = {}
	trajet = {}

	-- Détermination des durées de parcours pour chacune des routes
	
	for street in pairs(voie) do
		if xtime[street] ~= nil then
			upd=0
			for i in ipairs(chemin) do
				if chemin[i]==voie[street] then
					trajet[i]=trajet[i]+xtime[street]
					upd=1
				end
			end
			if upd == 0 and xtime[street]~=nil and voie[street]~=nil then 
				voir_les_logs("voie[street]="..voie[street])
				voir_les_logs("xtime[street]="..xtime[street])
				voir_les_logs("j="..j)
				chemin[j]=voie[street]
				if xtime[street]~=nil then
					trajet[j]=xtime[street]
				else
					trajet[j]=0
				end
				voir_les_logs("chemin["..tostring(j).."]="..chemin[j])
				voir_les_logs("trajet["..tostring(j).."]="..trajet[j])
				j=j+1
			end
		end
	end
	voie4T=0
	voie5T=0

	-- Recherche de deux routes les plus utilisées
	
	for i in ipairs(chemin) do
		voir_les_logs("chemin["..tostring(i).."]="..chemin[i])
		voir_les_logs("trajet["..tostring(i).."]="..trajet[i])
		if trajet[i]~=nil and chemin[i]~="/ND" then
			if trajet[i] > voie4T then 
				voie4N=chemin[i]
				voie4T=trajet[i]
			elseif trajet[i] > voie5T then 
				voie5N=chemin[i]
				voie5T=trajet[i]
			end
		end
	end
	voir_les_logs(voie4N.." "..voie5N)
	routeName=voie4N.." "..voie5N
	via_vehicule="voiture"
	for index in pairs(vehicleType) do
		if vehicleType[index] then via_vehicule=string.lower(index) end
	end
	routeName=routeName .. " en " .. string.lower(via_vehicule)
	routeName=string.gsub(routeName, "motorcycle", "moto")				-- Traduction en français
	routeTotalTime = os.date("%H:%M", routeTotalTimeSec-3600)..'&nbsppar&nbsp '..string.gsub(routeName, ' ', '&nbsp')
	commandArray[#commandArray+1]={['UpdateDevice'] =idx..'|0|' .. tostring(routeTotalTime)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_curve..'|0|' .. tostring(routeTotalTimeMin)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_duree..'|0|' .. tostring(os.date("%H.%M", routeTotalTimeSec-3600))}
	commandArray['Variable:Trajet-retour'] = tostring(routeTotalTimeMin)
end
return commandArray
Un bon frein vaut mieux que deux sparadraps.

Ubuntu 24.04.3 LTS - Domoticz 2025.1 (build 16782)
Pentium G3220T 2.6GHz - 4Go DDR3
RFXtrx433 USB Ver Pro1/1043
Z-Stick GEN5 Version: 1.6-1136-g07ea22bb
Rtl433 RTL-SDR receiver
RFLink Gateway
Zigbee SLZB-06
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: [LUA] Durée de trajet avec Waze

Message par garycooper »

Salut Chrominator, merci pour cette mise à jour qui fonctionne ! A priori le choix ["AVOID_TOLL_ROADS"] ne fonctionne pas car que je sois avec "true" or "false", le temps de trajet est le même et correspond au temps de trajet sans péage. J'ai comparé sur l'appli waze
Chrominator
Messages : 1042
Inscription : 19 déc. 2015, 07:29
Localisation : France

Re: [LUA] Durée de trajet avec Waze

Message par Chrominator »

Oui, je pensais que l'option était implicite mais non, il faut à chaque fois indiquer si on souhaite éviter les péages ou pas.

J'ai ajouté d'autres options, ce qui nous permet de jouer avec :
  • Eviter les routes non bitumées
  • Eviter les longues sections non bitumées
  • Autoriser les demi-tours
  • Eviter les routes à péage
  • Eviter les ferries et les bacs
  • Eviter les autoroutes urbaines et les voies express
  • Eviter les intersections difficiles
  • Utiliser les voies de covoiturage
J'ai le temps calculé pour un départ maintenant de la mairie de Marseille vers celle de Bruxelles par l'autoroute à péage.
Sans péage il y a trop de lignes et on retrouve la limitation de Domoticz.

J'ai ajouté dans le widget si le péage serait utilisé ou pas.

Screenshot 2021-12-09 at 13-05-26 Domoticz_dev.png
Screenshot 2021-12-09 at 13-05-26 Domoticz_dev.png (17.56 Kio) Consulté 3336 fois
Nouvelle version du script :

Code : Tout sélectionner

---------------------------------
-- Script de calcul de temps pour un trajet entre 2 coordonnées
-- Auteur : Neutrino
-- Date : 7 septembre 2015
-- Nécessite un capteur virtuel de type Text
-- source :
-- http://www.domo-blog.fr/info-trajet-waze-eedomus-version-raspberry/
---------------------------------
-- Modif Chrominator 
--
-- 	2016-01-30 : 	Remplacement des secondes du trajet par " mn"
--					Pas de détermination du temps de trajet les W-E et jours fériés
--	2017-11-11 : 	Détermination du nom des routes principales (les plus longtemps parcourues) car routeName n'existe plus dans le JSON
--
--	2021-11-10 : 	Mise à jour consécutive à des changements dans l'API (result, cross_time, street_name)
--					Ajout d'un custom sensor représentant la durée en heures/minutes
--
--  2021-12-08 :	Retour à l'ancienne forme du json par Waze - Adaptation en fonction de la version identifiée et à l'aide de pcall()
--					Ajout de critères de contournement (routes non bitumées, demi-tours, péages, ferries, covoiturage, voies express et intersections difficiles)
--					et du type de véhicule utilisé (defaut Voiture, alternative TAXI ou MOTORBIKE)
--					Suppression des lignes de réponse json inutiles pour le calcul de la durée de trajet
--					Ajout du terme Péage dans le widget si l'itinéraire utilise des voies payantes
--

DEBUG=true
local RUN=true

function voir_les_logs (s) -- nécessite la variable DEBUG
    if DEBUG then
      if s ~= nil then
        print (s)
      else
        print ("aucune valeur affichable")
      end
    end
end

commandArray={}

if RUN == false then return commandArray end

--import des fontions pour lire le JSON
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()

--variables à modifier----------------
--idx du capteur
idx = '1051'				-- Capteur de type texte pour afficher la durée du trajet et le nom de la principale route empruntée.
idx_curve = '1052'			-- Capteur de type voltmetre pour archiver les temps de parcours calculés
idx_duree = '1061'			-- Affiche un graphique en heure/minutes
-- y = latitude et x = longitude
--coordonnées de départ
departx="5.364967"	-- Mairie de Marseille
departy="43.304719"

-- Mairie de Bruxelles
arrivex="4.351390224944818"
arrivey="50.84638814089876"


---récupère l'heure actuelle en minutes
time=os.time()
minutes=tonumber(os.date('%M',time))
hours=tonumber(os.date('%H',time))
maintenant=tonumber(hours*60+minutes)

-- options pour l'API Waze
-- Mettre la valeur à true ou false en fonction de ce que vous voulez

local waze_options = {
	["AVOID_TRAILS"] = true,				-- Eviter les routes non bitumées
	["AVOID_LONG_TRAILS"] = true,			-- Eviter les longues sections non bitumées
	["ALLOW_UTURNS"] = false,				-- Autoriser les demi-tours
	["AVOID_TOLL_ROADS"] = false,			-- Eviter les routes à péage
	["AVOID_FERRIES"] = true,				-- Eviter les ferries et les bacs
	["AVOID_PRIMARIES"] = false,			-- Eviter les autoroutes urbaines et les voies express
	["AVOID_DANGEROUS_TURNS"] = false,		-- Eviter les intersections difficiles
	["ADD_HOV_ROUTES"] = false				-- Utiliser les voies de covoiturage
	}

local vehicleType = {						-- Un seul choix à true - si tous à false = voiture
	["MOTORCYCLE"] = false,
	["TAXI"] = false					
	}
	
local subscription = "*"					-- CRIT'AIR - A déterminer ce qu'il faut indiquer si on a pas de vignette CRIT'AIR

local useless_keys = {
	'"altStreets":null,',
	'"tiles":null,',
	'"clientIds":null,',
	'"laneType":null,',
	'"areas":null,',
	'"requiredPermits":null,',
	'"clientLaneSet":null,',
	'"roadSign":null,',
	'"detour":null,',
	'"naiveRoute":null,',
	'"detourSavingsNoRt":null,',
	'"detourRoute":null,',
	'"naiveRouteFullResult",:null',
	'"detourRouteFullResult":null,',
	'"instruction":null,',
	'"additionalInstruction":null,',
	'"knownDirection":true,',
	'"penalty":[0-9],',
	'"roadType":[0-9],',
	'"isToll":false,',
	'"useHovLane":false,',
	'"attributes":[0-9],',
	'"lane":"WHOLE_SEGMENT",',
	'"avoidStatus":"OPEN",',
	'"isInvalid":false,',
	'"isBlocked":false,',
	'"detourSavings":[0-9],',
    '"mergeOffset":[0-9],'
	}

function remove_garbage(json_string, garbage)
	print(type(json_string))
	print(type(garbage))
	infowaze, nb = string.gsub(json_string, garbage, " ")
	print(nb)
	return infowaze
end
	

-- Récupère le jour pour ne pas calculer de trajet les week-end.
-- Sunday = 0 - Saturday = 6
local weekday = os.date('%w')

---calcule du trajet entre 17h00 et 17h15
if (maintenant>=1020 and maintenant<= 1035 and weekday == 5) or DEBUG then

	-----------------------------------------
	----------------------------------------------------------------
	--Récupération du trajet et de sa durée en temps réel via WAZE--
	----------------------------------------------------------------
	-- Préparation de l'url
	url = "https://www.waze.com/row-RoutingManager/routingRequest?from=x%3A"..departx.."+y%3A"..departy.."&to=x%3A"..arrivex.."+y%3A"..arrivey.."&returnJSON=true&timeout=60000&nPaths=1&clientVersion=4.0.0&subscription=\"" .. tostring(subscription) .. "\""
	-- vérification des options
	local option_list = ""
	for option in pairs(waze_options) do
		if waze_options[option] then option_list = option_list .. option .. ":t," else option_list = option_list .. option .. ":f," end
	end
	local vehicule = ""
	for option in pairs(vehicleType) do
		if vehicleType[option] then option_list = option_list .. "vehicleType=" .. option .. "&" end
	end
	-- supprime le & ou la virgule supplémentaire
	option_list = option_list:sub(1, -2)
	voir_les_logs('curl --referer https://www.waze.com '.. '"' .. url .. '&options=' .. option_list..'"')
	local waze=assert(io.popen('curl --referer https://www.waze.com '.. '"' .. url .. '&options=' .. option_list..'"'))
	local infowaze = waze:read('*all')
	waze:close()
	for index in pairs(useless_keys) do
		infowaze = remove_garbage(infowaze, useless_keys[index])
	end
	local out = assert(io.open("infowaze", "wb"))
	out:write(infowaze)
	assert(out:close())
	local version_id = nil
	print(type(infowaze))
	local jsonTrajet = json:decode(infowaze)
	-- identification de la version de l'API Waze
	if pcall(function () routeName = jsonTrajet['response'][1]['route_name'] end) then 
		version_id=1 
		print("Version Waze #1 identifiée - nouvelle version de novembre 2021")
	end
	if pcall(function () routeName = jsonTrajet['response']['route_name'] end) then 
		version_id=0 
		print("Version Waze #0 identifiée - Ancienne version antérieure à novembre 2021")
	end
	if version_id == nil then print("Version Waze non reconnue ou trajet trop long - Sortie") return commandArray end
	--Noms des principales routes empruntées
	if version_id == 1 then routeName = jsonTrajet['response'][1]['route_name'] else routeName = jsonTrajet['response']['routeName'] end
	if routeName == nil then routeName="route non précisée" end
	voir_les_logs("RouteName="..routeName)
	--Liste des routes empruntées
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	--Temps de trajet en secondes
	routeTotalTimeSec = 0
	--calcul du temps de trajet
	for response,results in pairs(route) do
		if version_id == 1 then routeTotalTimeSec = routeTotalTimeSec + results['cross_time'] else routeTotalTimeSec = routeTotalTimeSec + results['crossTime'] end
	end
	
	--Temps de trajet en minutes
	routeTotalTimeMin = routeTotalTimeSec/60-((routeTotalTimeSec%60)/60)

	-- Détermination des noms des routes employées
	xtime = {}
	if version_id == 1 then route = jsonTrajet['response'][1]['result'] else route = jsonTrajet['response']['results'] end
	if version_id == 1 then voie = jsonTrajet['response'][1]['street_name'] else voie = jsonTrajet['response']['streetNames'] end
	for response,results in pairs(route) do
		i = tonumber(results['street'])
		if voie[i] == nil then voie[i] = "/ND" end
		if xtime[i]==nil then xtime[i]=0 end
		if version_id == 1 then xtime[i]=xtime[i]+tonumber(results['cross_time']) else xtime[i]=xtime[i]+tonumber(results['crossTime']) end
	end

	i=0
	j=1
	chemin = {}
	trajet = {}

	-- Détermination des durées de parcours pour chacune des routes
	
	for street in pairs(voie) do
		if xtime[street] ~= nil then
			upd=0
			for i in ipairs(chemin) do
				if chemin[i]==voie[street] then
					trajet[i]=trajet[i]+xtime[street]
					upd=1
				end
			end
			if upd == 0 and xtime[street]~=nil and voie[street]~=nil then 
				voir_les_logs("voie[street]="..voie[street])
				voir_les_logs("xtime[street]="..xtime[street])
				voir_les_logs("j="..j)
				chemin[j]=voie[street]
				if xtime[street]~=nil then
					trajet[j]=xtime[street]
				else
					trajet[j]=0
				end
				voir_les_logs("chemin["..tostring(j).."]="..chemin[j])
				voir_les_logs("trajet["..tostring(j).."]="..trajet[j])
				j=j+1
			end
		end
	end
	voie4T=0
	voie5T=0

	-- Recherche de deux routes les plus utilisées
	
	for i in ipairs(chemin) do
		voir_les_logs("chemin["..tostring(i).."]="..chemin[i])
		voir_les_logs("trajet["..tostring(i).."]="..trajet[i])
		if trajet[i]~=nil and chemin[i]~="/ND" then
			if trajet[i] > voie4T then 
				voie4N=chemin[i]
				voie4T=trajet[i]
			elseif trajet[i] > voie5T then 
				voie5N=chemin[i]
				voie5T=trajet[i]
			end
		end
	end
	voir_les_logs(voie4N.." "..voie5N)
	routeName=voie4N.." "..voie5N
	via_vehicule="voiture"
	for index in pairs(vehicleType) do
		if vehicleType[index] then via_vehicule=string.lower(index) end
	end
	routeName=routeName .. " en " .. string.lower(via_vehicule)
	routeName=string.gsub(routeName, "motorcycle", "moto")				-- Traduction en français
	-- Si on peut prendre les autoroutes à péage, on le signale dans le Widget
	if not waze_options["AVOID_TOLL_ROADS"] then routeName = routeName .. " - Péage" end
	routeTotalTime = os.date("%H:%M", routeTotalTimeSec-3600)..'&nbsppar&nbsp '..string.gsub(routeName, ' ', '&nbsp')
	commandArray[#commandArray+1]={['UpdateDevice'] =idx..'|0|' .. tostring(routeTotalTime)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_curve..'|0|' .. tostring(routeTotalTimeMin)}
	commandArray[#commandArray+1]={['UpdateDevice'] =idx_duree..'|0|' .. tostring(os.date("%H.%M", routeTotalTimeSec-3600))}
	commandArray['Variable:Trajet-retour'] = tostring(routeTotalTimeMin)
end
return commandArray
Un bon frein vaut mieux que deux sparadraps.

Ubuntu 24.04.3 LTS - Domoticz 2025.1 (build 16782)
Pentium G3220T 2.6GHz - 4Go DDR3
RFXtrx433 USB Ver Pro1/1043
Z-Stick GEN5 Version: 1.6-1136-g07ea22bb
Rtl433 RTL-SDR receiver
RFLink Gateway
Zigbee SLZB-06
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: [LUA] Durée de trajet avec Waze

Message par garycooper »

Bravo Chrominator ! Ton script est très abouti et personnalisable pour répondre à différentes attentes. Il fonctionne parfaitement
Répondre