Aller au contenu

Messages recommandés

Posté(e)

C'est fait. Voici une nouvelle version 0.4.

 

Cette nouvelle version apporte :

  • La décomposition du parcours sur chacune des étapes (changements) Maximum 9 étapes pour le moment.
  • Le temps de trajet global, ainsi que par étape
  • Le mode de circulation pour chacune des étape (La ligne à utiliser, Trajet à pied, Attente en gare, ...
  • La possibilité de choisir le mode retour (inversion entre le point de départ et d'arrivé). Attention pour le moment les flèches de navigation ne fonctionne pas pour le mode retour. Ca viendra.

Il suffit d'utiliser les 4 boutons du VD :

  • 1er    bouton recherche du prochain train au départ
  • 2ème bouton recherche du train en mode retour
  • 3ème bouton recherche du train suivant
  • 4ème bouton recherche du train précédent si l'itinéraire courant est supérieur à 1

Le label sous les bouton indique le Nième itinéraire courant.

 

Pour le moment, j'ai limité à 5 départs. Mais cela pourra être modifié facilement, si nécessaire.

 

1) Veuillez installer le nouveau VD ci-dessous :

 

Itinéraire_SNCF.vfib.json

 

Trop compliqué de fournir le code du VD (en mode texte) avec ses différents boutons qui contiennent chacun leur code.

 

Attention de bien :

  • copier vos codes Station de départ et d'arrivée dans chacun des 3 boutons
  • modifier la variable SceneID_Iti_SNCF par l'ID de la Scène Itinéraire SNCF

2) Veuillez charger le nouveau code de la scène :

 

Attention de bien :

  • modifier le contenu de la  variable User_API_Sncf par votre identifiant encodé en 64 dans la scène
  • modifier l'ID de votre Scène Sonos dans la variable SceneID_Sonos (si vous en possédez une enceinte)

3) Bons tests

 

PS : Les étapes suivantes du projet seront probablement consacré à 

  • la mixité des modes de transport entre (Trains, RER, BUS, Metro)
  • l'identification des incidents sur le trafic

Si vous avez d'autres idées, vous pouvez toujours faire vos demandes ;)

 

--[[
%% properties
%% events
%% globals
--]]

----------------------------------------------------------------------------------
-- Name : HC2 SNCF Itinéraire
-- Type : Virtual Device & Scene
-- Cette scène permet d'obtenir l'horaire du prochain train au départ d'une gare
----------------------------------------------------------------------------------
-- Le Projet :
--    Construire Virtual Device Affichant les données reccupérées
--    avec en option une notification vocale sur une enceinte SONOS en mode TTS
----------------------------------------------------------------------------------
-- Version  : 0.4
-- Création : MAM78
-- Date MAJ : 13/07/2017
--
-- Evolutions :
--   V0.1 09/07/2017 : Initialisation du projet
--   V0.2 10/07/2017 : Association de la scène à un VD qui appel la scène en
--					   passant les paramètres de la recherche d'itinéraire
--   V0.3 12/07/2017 : Ajouts de boutons de navigation pour parcourir les diférents
--					   itinéraires par odre chronologique des départs
--   V0.4 13/07/2017 : La décomposition du parcours sur chacune des étapes 
--                       (changements) Maximum 9 étapes pour le moment.
--                     Le temps de trajet global, ainsi que par étape
--                     Le mode de circulation pour chacune des étape
--					     (La ligne à utiliser, Trajet à pied, Attente en gare, ...
--					   La possibilité de choisir le mode retour (inversion entre
--                       le point de départ et d'arrivé). Attention pour le moment
--						 les flèches de navigation ne fonctionne pas pour le mode
--						 retour.
----------------------------------------------------------------------------------

-- User variables
local SceneID_Sonos = 61
local modetrace = true
local modedebug = true

----------------------------------------------------------------------------------
-- Pour pouvoir utiliser l'API de la SNCF, vous devez vous créer un compte sur :
--    https://data.sncf.com/api
-- Une fois votre compte créé vous recevrez un mail avec une clé d’authentification
-- Puis, vous devez vous connecter au site :
--    https://www.base64encode.org
-- Puis, encoder la clef reçu dans le mail ci-dessus
-- Copier ce code dans la vadiable ci-dessous (User_API_Sncf)
----------------------------------------------------------------------------------
-- local User_API_Sncf = "placé ici votre code API SNCF encodé en 64"

----------------------------------------------------------------------------------
-- Ne pas modifier le code ci-dessous, sinon pour l'adapter à votre usage
----------------------------------------------------------------------------------
local TimeOut = 3000
----------------------------------------------------------------------------------
-- Message pour mode Trace
----------------------------------------------------------------------------------
function Trace(color, message)
	if modetrace then 
        if color and color ~= "" then
            fibaro:debug('<span style="color:'..color..';">'..message..'</span>')
        else
            fibaro:debug(message)
        end
	end
end

----------------------------------------------------------------------------------
-- Message pour mode Debug
----------------------------------------------------------------------------------
function Debug(color, message)
	if modedebug then 
        if color and color ~= "" then
            fibaro:debug('<span style="color:'..color..';">'..message..'</span>')
        else
            fibaro:debug(message)
        end
    end
end

function SetUI(id, target, value)
  fibaro:call(id, "setProperty", "ui."..target..".value", value);
end

function SetUI_label(id, target, value)
  fibaro:call(id, "setProperty", "ui."..target..".label", value);
end

----------------------------------------------------------------------------------
-- Retourne le jour de la semaine en clair
----------------------------------------------------------------------------------
function josdGetJourSemaine(jour)
	josdGetJourSemaineTab={[0]="Dimanche",[1]="Lundi",[2]="Mardi",[3]="Mercredi",[4]="Jeudi",[5]="Vendredi",[6]="Samedi"}
	return josdGetJourSemaineTab[tonumber(jour)]
end

----------------------------------------------------------------------------------
-- Conversion un nombre de seconde en texte xhxmin" en format date
----------------------------------------------------------------------------------
function Conversion_Seconde_en_Texte(NbSec)

  Debug("grey","NbSec="..NbSec)
  
  local NbH=math.floor(NbSec/60/60)
  NbSec = NbSec - NbH * 60 * 60
  local NbM=math.floor(NbSec/60)
  NbSec = NbSec - NbH * 60
  if NbH > 0 then
    return NbH.."h"..NbM.."min"
  else
    return NbM.."min"
  end
end

----------------------------------------------------------------------------------
-- Conversion format date "aaaammjjThhmmss" en format date
----------------------------------------------------------------------------------
function Conversion_Date(dateheure)

    local TableDate = os.date("*t")
    TableDate.day = string.sub (dateheure, 7, 8)
    TableDate.month = string.sub (dateheure, 5, 6)
    TableDate.year = string.sub (dateheure, 1, 4)
    TableDate.hour = string.sub (dateheure, 10, 11)
    TableDate.min = string.sub (dateheure, 12, 13)
    return (os.time(TableDate))
end

function Affiche_Iti(data, Num_Traj)

  local Last_PT = nil
    
  local Nb_Iti = 0
  
  local Nb_Section = data.journeys[Num_Traj].sections
  
  local Max_Nb_Iti= 0
  
  if #Nb_Section > 9 then
    Max_Nb_Iti = 9
  else
    Max_Nb_Iti = #Nb_Section
  end
  
  Debug("grey","Nb_Section, Max_Nb_Iti="..#Nb_Section..", "..Max_Nb_Iti)
  
  for Num_Iti = 1 , Max_Nb_Iti do
      
      Debug("grey","Traitement Trajet-Itinéraire, type : "..Num_Traj.."-"..Num_Iti.." ,"..data.journeys[Num_Traj].sections[Num_Iti].type)
      
      if data.journeys[Num_Traj].sections[Num_Iti].type == "public_transport" then
        Last_PT = Num_Iti
      end
      
      local Date_Time = Conversion_Date(data.journeys[Num_Traj].sections[Num_Iti].departure_date_time)              
        
      local Lbl_message = "("..Conversion_Seconde_en_Texte(tonumber(data.journeys[Num_Traj].sections[Num_Iti].duration))..")"
        
      local Date_Time = Conversion_Date(data.journeys[Num_Traj].sections[Num_Iti].arrival_date_time)
      Lbl_message = Lbl_message.." -> "..os.date("%H:%M", Date_Time)
  
      if data.journeys[Num_Traj].sections[Num_Iti].type == "waiting" then
          Lbl_message = Lbl_message.." à " ..data.journeys[Num_Traj].sections[Num_Iti-1].to.stop_point.name
          Lbl_message = Lbl_message.." -> " .."[En ATTENTE]"
      else
        if data.journeys[Num_Traj].sections[Num_Iti].type == "walking" then
          Lbl_message = Lbl_message.." -> " ..data.journeys[Num_Traj].sections[Num_Iti].to.stop_point.name
          Lbl_message = Lbl_message.." -> " .."[à PIED]"
        else
          if data.journeys[Num_Traj].sections[Num_Iti].type == "transfer" then
            if data.journeys[Num_Traj].sections[Num_Iti].transfer_type == "walking" then
              Lbl_message = Lbl_message.." -> " ..data.journeys[Num_Traj].sections[Num_Iti].to.stop_point.name
              Lbl_message = Lbl_message.." -> " .."[à PIED]"
            end
          else
            if data.journeys[Num_Traj].sections[Num_Iti].type == "crow_fly" then
              if data.journeys[Num_Traj].sections[Num_Iti].mode == "walking" then
                Lbl_message = Lbl_message.." -> " ..data.journeys[Num_Traj].sections[Num_Iti].to.stop_point.name
                Lbl_message = Lbl_message.." -> " .."[à PIED]"
              end
            else
              Lbl_message = Lbl_message.." -> " ..data.journeys[Num_Traj].sections[Num_Iti].to.stop_point.name
              Lbl_message = Lbl_message.." ["..data.journeys[Num_Traj].sections[Num_Iti].display_informations.commercial_mode .." / "..data.journeys[Num_Traj].sections[Num_Iti].display_informations.code.."]"
            end
          end
        end
      end
    
      Nb_Iti = Nb_Iti + 1
  
      SetUI(VD_Id, "lblIti"..Num_Iti, Lbl_message)
  end
  
  
  if Max_Nb_Iti < 9 then
    for i = Max_Nb_Iti + 1, 9 do
      SetUI(VD_Id, "lblIti"..i, " ")
    end
  end
  
  SetUI(VD_Id, "lblFromTo", fibaro:get(VD_Id, "ui.lblFromTo.value").. " -> " ..data.journeys[Num_Traj].sections[Last_PT].to.stop_point.name)
  
end

function Affiche_Traj(data)
  
  local Num_Traj = fibaro:get(VD_Id, "ui.lblNum.value")
  Num_Traj = tonumber(Num_Traj)
  
  Trace("blue","Traitement Trajet : "..Num_Traj)
  
  --fibaro:call(VD_Id, "setProperty", "ui.lblDep2.label", "&#x2648")
  --fibaro:call(VD_Id, "setProperty", "ui.lblDep2.label", "XX\00000aXX")
    
  SetUI(VD_Id, "lblFromTo", data.journeys[Num_Traj].sections[1].from.stop_point.name)
  --SetUI(VD_Id, "lblDir", data.journeys[Num_Traj].sections[1].display_informations.direction) 
  
  if data.journeys[Num_Traj].status =="" then
    SetUI(VD_Id, "lblTrafic", "normal") 
  else
    SetUI(VD_Id, "lblTrafic", data.journeys[Num_Traj].status)
  end

  local Date_Time = Conversion_Date(data.journeys[Num_Traj].departure_date_time)              
    
  local Lbl_message = "à "..os.date("%H:%M", Date_Time)
    
  local Date_Time = Conversion_Date(data.journeys[Num_Traj].arrival_date_time)              
      
  Lbl_message = Lbl_message .." -> "..os.date("%H:%M", Date_Time).." ("..Conversion_Seconde_en_Texte(tonumber(data.journeys[Num_Traj].duration))..")"
  
  SetUI(VD_Id, "lblDepArr", Lbl_message)

  Affiche_Iti(data, Num_Traj)

end
----------------------------------------------------------------------------------
-- Traitement des données en provenance de l'IPA SNCF
----------------------------------------------------------------------------------
function GetData()

  Debug("grey","T1".." - "..Iti_Titre)
  -- https://api.sncf.com/v1/coverage/sncf
  -- /journeys?
  -- from=stop_area:OCE:SA:87382473&
  -- to=stop_area:OCE:SA:87382218&
  -- datetime='20170716T040000'&
  -- datetime_represents=departure&
  -- min_nb_journeys=4
  local api_url = "https://api.sncf.com/v1"
  local api_coverage = "sncf"
  local api_fonction = "journeys?"
  local api_from = code_api_from
  local api_to = code_api_to
  local api_datetime = os.date("%Y%m%dT%H%M00", os.time())
  local api_datetime_represents = "departure"
  local api_min_nb_journeys = "5"

  local Query = api_url
  local Query = Query .. "/coverage/" .. api_coverage
  local Query = Query .. "/" .. api_fonction
  local Query = Query .. "from=" .. api_from.."&"
  local Query = Query .. "to=" .. api_to.."&"
  local Query = Query .. "datetime=" .. api_datetime.."&"
  local Query = Query .. "datetime_represents=" .. api_datetime_represents.."&"
  local Query = Query .. "min_nb_journeys=" .. api_min_nb_journeys
  
  Debug("grey","T2".." - "..Iti_Titre)
    
  local http = net.HTTPClient({ timeout = TimeOut })
  
  Debug("grey","T3".." - "..Iti_Titre)
  
  Debug("grey",Query)
  
  local ok = pcall(function() http:request(Query, {
      options = { 
        method = 'GET', 
        headers ={
              ["Content-Type"] = "application/json",
              ["Authorization"] = "BASIC "..User_API_Sncf},           
        data = body
        },
      
      success = function(response)
            
        Debug("grey","T4".." - "..Iti_Titre)
              
	    if response.status == 200 then
          
          Debug("grey","T5".." - "..Iti_Titre)
          Trace("blue","Traitement ok : "..Iti_Titre)
          local status, data = pcall(json.decode, response.data)
            
          if (status and data) then
                
            Affiche_Traj(data)
                  
            Trace("green","Départ : "..data.journeys[1].sections[1].from.stop_point.name)
            Trace("green","Direction : "..data.journeys[1].sections[1].to.stop_point.name) 
                                
            local Date_Time = Conversion_Date(data.journeys[1].sections[1].departure_date_time)              
            local Horaire = tostring(tonumber(os.date("%H", Date_Time))) .. " heure ".. tostring(tonumber(os.date("%M", Date_Time)))
            local JourSemaine = josdGetJourSemaine(os.date("%w", MonHeure))
                
            -- Test pour vérifier si le prochain départ est pour le jour même
            if os.date("%Y/%m/%d",Date_Time) == os.date("%Y/%m/%d",time) then
              Prochain_Depart = "aujourd'hui"
            else
              Prochain_Depart = JourSemaine
            end
                
            Trace("green", "Prochain départ "..Prochain_Depart.." à " ..os.date("%H:%M", Date_Time))

            message = "Prochain départ"
            message = message .. " "..Prochain_Depart
            message = message .. " de "..Msg_Depart
            message = message .. " pour "..Msg_Arrivee
            message = message .. " a ".. Horaire
                  
            local Date_Time = Conversion_Date(data.journeys[1].sections[1].arrival_date_time)              
            local Horaire = tostring(tonumber(os.date("%H", Date_Time))) .. " heure ".. tostring(tonumber(os.date("%M", Date_Time)))
            local JourSemaine = josdGetJourSemaine(os.date("%w", Date_Time))
                
            message = message .. " Arrivée à "..Horaire
                
            Trace("green", "Arrivée à " ..os.date("%H:%M", Date_Time))
                                
            -- Envoi d'un message sur l'enceinte SONOS
            if Msg_Sonos == "OUI" then    
              Debug("grey", "Envoi Message sur enceinte SONOS")
                  
              fibaro:startScene(SceneID_Sonos, {{msg = message}, {vol = Volume_Sonos}})
            end                
                
          else
            Trace("orange"," Attention : Aucunes données à traiter")
          end
        else
          Debug("grey","T6".." - "..Iti_Titre)
          Trace("yellow","Traitement ko : "..Iti_Titre)
              
          if response.status == 500 or response.status == 503 then
            Trace("orange","Erreur d'indisponibilité du serveur")
          else
            Trace("orange","Erreur requête serveur, response.status = "..response.status)
          end    
        end
      end,
      
      error = function(err)
        Debug("grey","T7".." - "..Iti_Titre)
        Trace("orange","Erreur de reception de données, Erreur = ".. err)
      end
  })
  
  end)
  if not(ok) then
    Trace("orange","Erreur dans l'exécution de fhttp:request(Query")
  end
  Debug("grey","T9".." - "..Iti_Titre)

end
  
function Start()

  Debug("grey","VD_Id="..VD_Id.." / Volume_Sonos="..Volume_Sonos.." / Msg_Sonos="..Msg_Sonos)

  -- test pour vérifier si le module virtuel exist ou pas
  local ip = fibaro:get(VD_Id, 'IPAddress')
  if ip == nil then
    Debug("orange","Warning : Le module virtuel : "..VD_Id.." n'existe pas. Vous devez le créer !")
  else
    -- Lancement du traitement de l'itinéraire
    GetData()
  end
end


-------------------------------------------------------------------------------
-- Begining off Scène
-------------------------------------------------------------------------------
local params = fibaro:args()

Trace("orange","Début de traitement de la scène")

if (params) then

  for k, v in ipairs(params) do

    if (v.Iti_Titre) then Iti_Titre = v.Iti_Titre end    
    if (v.code_api_to) then code_api_to = v.code_api_to end
    if (v.code_api_from) then code_api_from = v.code_api_from end
    if (v.Msg_Arrivee) then Msg_Arrivee = v.Msg_Arrivee end
    if (v.Msg_Depart) then Msg_Depart = v.Msg_Depart end
    if (v.Msg_Sonos) then Msg_Sonos = v.Msg_Sonos end
    if (v.Volume_Sonos) then Volume_Sonos = v.Volume_Sonos end
    if (v.VD_Id) then VD_Id = v.VD_Id end
    
  end
                   
  Start()
else
  Trace("orange","Erreur : Cette scène fonctionne par appel depuis un VD avec un passage de paramètres")
end

Trace("orange","Fin de traitement de la scène")

 

  • Upvote 2
Posté(e)

@MAM78

 

Salut, 

je testerai la V4 ce soir ou dans la week-end....

 

En tout cas sacré boulot que tout ça , toutes ces lignes de code , le temps que tu y passes et la rapidité à modifier/adapter en fonction de nos besoins/demandes ...

 

Un grand Bravo et encore MERCI !!!:13::60::16:  

Posté(e) (modifié)

hello

 

pas de difference quand je click sur le trajet retour ? normal ?

 

et un peu too much les 9 changement lol...

 

ALLER / RETOUR

A.png

R.png

Modifié par Sakkhho
Posté(e)

Voici une nouvelle version 0.5

 

Cette nouvelle version apporte :

  • La possibilité de choisir le mode retour (inversion entre le point de départ et d'arrivé)
  • Il n'est plus nécessaire de modifier les variables (from et to) sur le bouton retour. Spécial dédicace @Sakkhho
  • Possibilité d'utiliser les flèches de navigation que ce soit pour un trajet Aller ou Retour

Il suffit d'utiliser les 4 boutons du VD :

  • 1er    bouton recherche du prochain train au départ
  • 2ème bouton recherche du train en mode retour
  • 3ème bouton recherche du train suivant
  • 4ème bouton recherche du train précédent si l'itinéraire courant est supérieur à 1

Le label sous les bouton indique le Nième itinéraire courant avec précision du sens du trajet.

 

Pour le moment, j'ai limité à 5 départs. Mais cela pourra être modifié facilement, si nécessaire.

 

1) Veuillez installer le nouveau VD ci-dessous :

 

Itinéraire_SNCF.vfib.json

 

Trop compliqué de fournir le code du VD (en mode texte) avec ses différents boutons qui contiennent chacun leur code. Désolé @Sakkhho :13:

 

Attention de bien :

  • copier vos codes Station de départ et d'arrivée dans chacun des 3 boutons
  • modifier la variable SceneID_Traj_SNCF par l'ID de la Scène Itinéraire SNCF

2) Veuillez charger le nouveau code de la scène :

 

Attention de bien :

  • modifier le contenu de la  variable User_API_Sncf par votre identifiant encodé en 64 dans la scène
  • modifier l'ID de votre Scène Sonos dans la variable SceneID_Sonos (si vous en possédez une enceinte)

3) Bons tests

 

PS : Les étapes suivantes du projet seront probablement consacré à 

  • la mixité des modes de transport entre (Trains, RER, BUS, Metro)
  • l'identification des incidents sur le trafic (retard)

Si vous avez d'autres idées, vous pouvez toujours faire vos demandes ;)

 

--[[
%% properties
%% events
%% globals
--]]

----------------------------------------------------------------------------------
-- Name : HC2 SNCF Itinéraire
-- Type : Virtual Device & Scene
-- Cette scène permet d'obtenir l'horaire du prochain train au départ d'une gare
----------------------------------------------------------------------------------
-- Le Projet :
--    Construire Virtual Device Affichant les données reccupérées
--    avec en option une notification vocale sur une enceinte SONOS en mode TTS
----------------------------------------------------------------------------------
-- Version  : 0.5
-- Création : MAM78
-- Date MAJ : 09/07/2017
--
-- Evolutions :
--   V0.1 09/07/2017 : Initialisation du projet
--   V0.2 10/07/2017 : Association de la scène à un VD qui appel la scène en
--					   passant les paramètres de la recherche d'itinéraire
--   V0.3 12/07/2017 : Ajouts de boutons de navigation pour parcourir les diférents
--					   itinéraires par odre chronologique des départs
--   V0.4 13/07/2017 : La décomposition du parcours sur chacune des étapes 
--                       (changements) Maximum 9 étapes pour le moment.
--                     Le temps de trajet global, ainsi que par étape
--                     Le mode de circulation pour chacune des étape
--                       (La ligne à utiliser, Trajet à pied, Attente en gare, ...
--					   La possibilité de choisir le mode retour (inversion entre
--                       le point de départ et d'arrivé). Attention pour le moment
--                       les flèches de navigation ne fonctionne pas pour le mode
--                       retour.
--					   Possibilité d'utiliser les flèches de navigation que ce
--                       soit pour un trajet Aller ou Retour
----------------------------------------------------------------------------------

-- User variables
local SceneID_Sonos = 61
local modetrace = true
local modedebug = true

----------------------------------------------------------------------------------
-- Pour pouvoir utiliser l'API de la SNCF, vous devez vous créer un compte sur :
--    https://data.sncf.com/api
-- Une fois votre compte créé vous recevrez un mail avec une clé d’authentification
-- Puis, vous devez vous connecter au site :
--    https://www.base64encode.org
-- Puis, encoder la clef reçu dans le mail ci-dessus
-- Copier ce code dans la vadiable ci-dessous (User_API_Sncf)
----------------------------------------------------------------------------------
local User_API_Sncf = "placé ici votre code API SNCF encodé en 64"

----------------------------------------------------------------------------------
-- Ne pas modifier le code ci-dessous, sinon pour l'adapter à votre usage
----------------------------------------------------------------------------------
local TimeOut = 3000
----------------------------------------------------------------------------------
-- Message pour mode Trace
----------------------------------------------------------------------------------
function Trace(color, message)
	if modetrace then 
        if color and color ~= "" then
            fibaro:debug('<span style="color:'..color..';">'..message..'</span>')
        else
            fibaro:debug(message)
        end
	end
end

----------------------------------------------------------------------------------
-- Message pour mode Debug
----------------------------------------------------------------------------------
function Debug(color, message)
	if modedebug then 
        if color and color ~= "" then
            fibaro:debug('<span style="color:'..color..';">'..message..'</span>')
        else
            fibaro:debug(message)
        end
    end
end

function SetUI(id, target, value)
  fibaro:call(id, "setProperty", "ui."..target..".value", value);
end

function SetUI_label(id, target, value)
  fibaro:call(id, "setProperty", "ui."..target..".label", value);
end

----------------------------------------------------------------------------------
-- Retourne le jour de la semaine en clair
----------------------------------------------------------------------------------
function josdGetJourSemaine(jour)
	josdGetJourSemaineTab={[0]="Dimanche",[1]="Lundi",[2]="Mardi",[3]="Mercredi",[4]="Jeudi",[5]="Vendredi",[6]="Samedi"}
	return josdGetJourSemaineTab[tonumber(jour)]
end

----------------------------------------------------------------------------------
-- Conversion un nombre de seconde en texte xhxmin" en format date
----------------------------------------------------------------------------------
function Conversion_Seconde_en_Texte(NbSec)

  Debug("grey","NbSec="..NbSec)
  
  local NbH=math.floor(NbSec/60/60)
  NbSec = NbSec - NbH * 60 * 60
  local NbM=math.floor(NbSec/60)
  NbSec = NbSec - NbH * 60
  if NbH > 0 then
    return NbH.."h"..NbM.."min"
  else
    return NbM.."min"
  end
end

----------------------------------------------------------------------------------
-- Conversion format date "aaaammjjThhmmss" en format date
----------------------------------------------------------------------------------
function Conversion_Date(dateheure)

    local TableDate = os.date("*t")
    TableDate.day = string.sub (dateheure, 7, 8)
    TableDate.month = string.sub (dateheure, 5, 6)
    TableDate.year = string.sub (dateheure, 1, 4)
    TableDate.hour = string.sub (dateheure, 10, 11)
    TableDate.min = string.sub (dateheure, 12, 13)
    return (os.time(TableDate))
end

function Affiche_Iti(data, Traj_Num)

  local Last_PT = nil
    
  local Nb_Iti = 0
  
  local Nb_Section = data.journeys[Traj_Num].sections
  
  local Max_Nb_Iti= 0
  
  if #Nb_Section > 9 then
    Max_Nb_Iti = 9
  else
    Max_Nb_Iti = #Nb_Section
  end
  
  Debug("grey","Nb_Section, Max_Nb_Iti="..#Nb_Section..", "..Max_Nb_Iti)
  
  for Num_Iti = 1 , Max_Nb_Iti do
      
      Debug("grey","Traitement Trajet-Itinéraire, type : "..Traj_Num.."-"..Num_Iti.." ,"..data.journeys[Traj_Num].sections[Num_Iti].type)
      
      if data.journeys[Traj_Num].sections[Num_Iti].type == "public_transport" then
        Last_PT = Num_Iti
      end
      
      local Date_Time = Conversion_Date(data.journeys[Traj_Num].sections[Num_Iti].departure_date_time)              
        
      local Lbl_message = "("..Conversion_Seconde_en_Texte(tonumber(data.journeys[Traj_Num].sections[Num_Iti].duration))..")"
        
      local Date_Time = Conversion_Date(data.journeys[Traj_Num].sections[Num_Iti].arrival_date_time)
      Lbl_message = Lbl_message.." -> "..os.date("%H:%M", Date_Time)
  
      if data.journeys[Traj_Num].sections[Num_Iti].type == "waiting" then
          Der_Dest = data.journeys[Traj_Num].sections[Num_Iti-1].to.stop_point.name
          Lbl_message = Lbl_message.." à " ..Der_Dest
      	  Lbl_message = Lbl_message.." -> " .."[En ATTENTE]"
      else
        if data.journeys[Traj_Num].sections[Num_Iti].type == "walking" then
          Der_Dest = data.journeys[Traj_Num].sections[Num_Iti].to.stop_point.name
          Lbl_message = Lbl_message.." à " ..Der_Dest
          Lbl_message = Lbl_message.." -> " .."[à PIED]"
        else
          if data.journeys[Traj_Num].sections[Num_Iti].type == "transfer" then
            if data.journeys[Traj_Num].sections[Num_Iti].transfer_type == "walking" then
              Der_Dest = data.journeys[Traj_Num].sections[Num_Iti].to.stop_point.name
              Lbl_message = Lbl_message.." à " ..Der_Dest
              Lbl_message = Lbl_message.." -> " .."[à PIED]"
            end
          else
            if data.journeys[Traj_Num].sections[Num_Iti].type == "crow_fly" then
              if data.journeys[Traj_Num].sections[Num_Iti].mode == "walking" then
                Der_Dest = data.journeys[Traj_Num].sections[Num_Iti].to.stop_point.name
                Lbl_message = Lbl_message.." à " ..Der_Dest
                Lbl_message = Lbl_message.." -> " .."[à PIED]"
              end
            else
              Der_Dest = data.journeys[Traj_Num].sections[Num_Iti].to.stop_point.name
              Lbl_message = Lbl_message.." à " ..Der_Dest
              Lbl_message = Lbl_message.." ["..data.journeys[Traj_Num].sections[Num_Iti].display_informations.commercial_mode .." / "..data.journeys[Traj_Num].sections[Num_Iti].display_informations.code.."]"
            end
          end
        end
      end
    
      Nb_Iti = Nb_Iti + 1
  
      SetUI(VD_Id, "lblIti"..Num_Iti, Lbl_message)
  end
  
  
  if Max_Nb_Iti < 9 then
    for i = Max_Nb_Iti + 1, 9 do
      SetUI(VD_Id, "lblIti"..i, " ")
    end
  end
  
  SetUI(VD_Id, "lblFromTo", fibaro:get(VD_Id, "ui.lblFromTo.value").. " -> " ..Der_Dest)
  
end

function Affiche_Traj(data)
  
  local Traj_Num = tonumber(string.sub(fibaro:get(VD_Id, "ui.lblNum.value"), -1))

  Trace("blue","Traitement Trajet : "..Traj_Num)
  
  --fibaro:call(VD_Id, "setProperty", "ui.lblDep2.label", "&#x2648")
  --fibaro:call(VD_Id, "setProperty", "ui.lblDep2.label", "XX\00000aXX")
    
  SetUI(VD_Id, "lblFromTo", data.journeys[Traj_Num].sections[1].from.stop_point.name)
  --SetUI(VD_Id, "lblDir", data.journeys[Num_Traj].sections[1].display_informations.direction) 
  
  if data.journeys[Traj_Num].status =="" then
    SetUI(VD_Id, "lblTrafic", "normal") 
  else
    SetUI(VD_Id, "lblTrafic", data.journeys[Traj_Num].status)
  end

  local Date_Time = Conversion_Date(data.journeys[Traj_Num].departure_date_time)              
    
  local Lbl_message = "à "..os.date("%H:%M", Date_Time)
    
  local Date_Time = Conversion_Date(data.journeys[Traj_Num].arrival_date_time)              
      
  Lbl_message = Lbl_message .." -> "..os.date("%H:%M", Date_Time).." ("..Conversion_Seconde_en_Texte(tonumber(data.journeys[Traj_Num].duration))..")"
  
  SetUI(VD_Id, "lblDepArr", Lbl_message)

  Affiche_Iti(data, Traj_Num)

end
----------------------------------------------------------------------------------
-- Traitement des données en provenance de l'IPA SNCF
----------------------------------------------------------------------------------
function GetData()

  Debug("grey","T1".." - "..Traj_Titre)
  -- https://api.sncf.com/v1/coverage/sncf
  -- /journeys?
  -- from=stop_area:OCE:SA:87382473&
  -- to=stop_area:OCE:SA:87382218&
  -- datetime='20170716T040000'&
  -- datetime_represents=departure&
  -- min_nb_journeys=4
  local api_url = "https://api.sncf.com/v1"
  local api_coverage = "sncf"
  local api_fonction = "journeys?"
  
  local Traj_Sens = string.sub(fibaro:get(VD_Id, "ui.lblNum.value"), 1, 1)

  local api_from = ""
  local api_to = ""
  
  if Traj_Sens == "A" then
    api_from = code_api_from
    api_to = code_api_to
  else
    api_from = code_api_to
    api_to = code_api_from
  end
  
  local api_datetime = os.date("%Y%m%dT%H%M00", os.time())
  local api_datetime_represents = "departure"
  local api_min_nb_journeys = "5"

  local Query = api_url
  local Query = Query .. "/coverage/" .. api_coverage
  local Query = Query .. "/" .. api_fonction
  local Query = Query .. "from=" .. api_from.."&"
  local Query = Query .. "to=" .. api_to.."&"
  local Query = Query .. "datetime=" .. api_datetime.."&"
  local Query = Query .. "datetime_represents=" .. api_datetime_represents.."&"
  local Query = Query .. "min_nb_journeys=" .. api_min_nb_journeys
  
  Debug("grey","T2".." - "..Traj_Titre)
    
  local http = net.HTTPClient({ timeout = TimeOut })
  
  Debug("grey","T3".." - "..Traj_Titre)
  
  Debug("grey",Query)
  
  local ok = pcall(function() http:request(Query, {
      options = { 
        method = 'GET', 
        headers ={
              ["Content-Type"] = "application/json",
              ["Authorization"] = "BASIC "..User_API_Sncf},           
        data = body
        },
      
      success = function(response)
            
        Debug("grey","T4".." - "..Traj_Titre)
              
	    if response.status == 200 then
          
          Debug("grey","T5".." - "..Traj_Titre)
          Trace("blue","Traitement ok : "..Traj_Titre)
          local status, data = pcall(json.decode, response.data)
            
          if (status and data) then
                
            Affiche_Traj(data)
                  
            Trace("green","Départ : "..data.journeys[1].sections[1].from.stop_point.name)
            Trace("green","Direction : "..data.journeys[1].sections[1].to.stop_point.name) 
                                
            local Date_Time = Conversion_Date(data.journeys[1].sections[1].departure_date_time)              
            local Horaire = tostring(tonumber(os.date("%H", Date_Time))) .. " heure ".. tostring(tonumber(os.date("%M", Date_Time)))
            local JourSemaine = josdGetJourSemaine(os.date("%w", MonHeure))
                
            -- Test pour vérifier si le prochain départ est pour le jour même
            if os.date("%Y/%m/%d",Date_Time) == os.date("%Y/%m/%d",time) then
              Prochain_Depart = "aujourd'hui"
            else
              Prochain_Depart = JourSemaine
            end
                
            Trace("green", "Prochain départ "..Prochain_Depart.." à " ..os.date("%H:%M", Date_Time))

            message = "Prochain départ"
            message = message .. " "..Prochain_Depart
            message = message .. " de "..Msg_Depart
            message = message .. " pour "..Msg_Arrivee
            message = message .. " a ".. Horaire
                  
            local Date_Time = Conversion_Date(data.journeys[1].sections[1].arrival_date_time)              
            local Horaire = tostring(tonumber(os.date("%H", Date_Time))) .. " heure ".. tostring(tonumber(os.date("%M", Date_Time)))
            local JourSemaine = josdGetJourSemaine(os.date("%w", Date_Time))
                
            message = message .. " Arrivée à "..Horaire
                
            Trace("green", "Arrivée à " ..os.date("%H:%M", Date_Time))
                                
            -- Envoi d'un message sur l'enceinte SONOS
            if Msg_Sonos == "OUI" then    
              Debug("grey", "Envoi Message sur enceinte SONOS")
                  
              fibaro:startScene(SceneID_Sonos, {{msg = message}, {vol = Volume_Sonos}})
            end                
                
          else
            Trace("orange"," Attention : Aucunes données à traiter")
          end
        else
          Debug("grey","T6".." - "..Traj_Titre)
          Trace("yellow","Traitement ko : "..Traj_Titre)
              
          if response.status == 500 or response.status == 503 then
            Trace("orange","Erreur d'indisponibilité du serveur")
          else
            Trace("orange","Erreur requête serveur, response.status = "..response.status)
          end    
        end
      end,
      
      error = function(err)
        Debug("grey","T7".." - "..Traj_Titre)
        Trace("orange","Erreur de reception de données, Erreur = ".. err)
      end
  })
  
  end)
  if not(ok) then
    Trace("orange","Erreur dans l'exécution de fhttp:request(Query")
  end
  Debug("grey","T9".." - "..Traj_Titre)

end
  
function Start()

  Debug("grey","VD_Id="..VD_Id.." / Volume_Sonos="..Volume_Sonos.." / Msg_Sonos="..Msg_Sonos)

  -- test pour vérifier si le module virtuel exist ou pas
  local ip = fibaro:get(VD_Id, 'IPAddress')
  if ip == nil then
    Debug("orange","Warning : Le module virtuel : "..VD_Id.." n'existe pas. Vous devez le créer !")
  else
    -- Lancement du traitement de l'itinéraire
    GetData()
  end
end


-------------------------------------------------------------------------------
-- Begining off Scène
-------------------------------------------------------------------------------
local params = fibaro:args()

Trace("orange","Début de traitement de la scène")

if (params) then

  for k, v in ipairs(params) do

    if (v.Traj_Titre) then Traj_Titre = v.Traj_Titre end    
    if (v.code_api_to) then code_api_to = v.code_api_to end
    if (v.code_api_from) then code_api_from = v.code_api_from end
    if (v.Msg_Arrivee) then Msg_Arrivee = v.Msg_Arrivee end
    if (v.Msg_Depart) then Msg_Depart = v.Msg_Depart end
    if (v.Msg_Sonos) then Msg_Sonos = v.Msg_Sonos end
    if (v.Volume_Sonos) then Volume_Sonos = v.Volume_Sonos end
    if (v.VD_Id) then VD_Id = v.VD_Id end

  end
  Start()
else
  Trace("orange","Erreur : Cette scène fonctionne par appel depuis un VD avec un passage de paramètres")
end

Trace("orange","Fin de traitement de la scène")

 

Posté(e) (modifié)

ha merde je viens juste de l'importer...

passe le code des boutons en MP ca doit le faire si c'est le meme labels/boutons que l'ancien non ?

merci

Modifié par Sakkhho
Posté(e)

oui probablement.

 

Je ne pense pas pouvoir identifier les trains annulés. Le principe même de l'API est de trouver le prochain train au départ. Donc celui qui est annulé, ne sera pas proposé.

 

Je vais donc regarder le sujet les retards, puisqu'il semble que l'info est disponible.

 

Il me faut trouver des exemples pour pouvoir faire de tests.

 

Posté(e)
il y a 48 minutes, MAM78 a dit :

Il me faut trouver des exemples pour pouvoir faire de tests.

@MAM78

 

Alors là des retards , tu devrais en trouver facilement....!! :P

 

En tout la V5 , est top :  (par contre tu peux m'expliquer à quoi vont servir les toutes les colonnes ?)

 

sncf9.thumb.JPG.7998a713e6d1b24c81533b9f3af29233.JPG

 

 

A ton avis , est il possible de programmer l’exécution du  VD  (avec tasker ou macrodroid ) et de faire une notification par sms ou mail  ou popup HC2 ?

 

Par exemple ,

  1. au lever le VD s’exécute et me notifie sur mon phone  des horaires et de l’état du traffic.
  2. Je sors du bureau (fin de journée de travail ) ,le VD s’exécute et me notifie sur mon phone  des horaires et de l’état du traffic.

Encore Merci

 

Posté(e) (modifié)

Pas besoin de tasser ou macrodroid, tu utilises GEA dans lequel tu programmes un événement qui va simuler un clic sur le bouton de ton choix (Aller ou Retour)

 

Tu peux même faire cela régulièrement (5 min.) pour rafraichir les données.

 

Ok je vais regarder cette histoire de notification. Mais une fois que j'aurais trouvé le moyen de détecter les retards.

 

Concernant les différents numéros, il s'agit d'étapes (changements) lors d'un trajet.

Modifié par MAM78
Posté(e)
il y a 2 minutes, MAM78 a dit :

Ok je vais regarder cette histoire de notification. Mais une fois que j'aurais trouvé le moyen de détecter les retards.

Ok , pas de soucis .... 

je ne te mets pas la pression...

la pression , il faut la boire !!!!   :77:

 

je vais regarder pour GEA que je vais découvrir par la même occasion ...;)

Posté(e) (modifié)

Je sais pas si possible mais plus que les retards c est l état du trafic qui est important (pour les parisiens). (Il y a des trains tous les 5". Donc retard est pas intéressant de savoir. Pas contre si trafic interrompu / perturbe / très perturbé etc ... demande peu être de prendre plan B ou de rester au bureau plus longtemps le temps que ca revienne à la normale )

Trafic perturbé en ce moment et pour la matinée je pense sur RER A. ;-)
Avec l api RATP qui renvoi l état (message court que je pousse sur le vd) et aussi en message long la cause que je pousse en notification.

 

"line": "A",
                "slug": "alerte",
                "title": "Trafic perturbé",
                "message": "14/07/17, 07:05, la gare Etoile est fermée, corresp. assurées (manifestation)"



bcdde6d324f15d47cf62f5010e376331.jpg

Modifié par Sakkhho
  • Upvote 2
Posté(e) (modifié)

Voici une nouvelle version 0.6

 

Cette nouvelle version apporte :

  1. Affichage d'alertes sur les retards au départ/arrivée avec la cause (si disponible)
  2. Consolidation de l'ensemble des paramètres des trajets dans la scène pour simplifier leur mise à jour et les rassemblent à un seul et même endroit
  3. Possibilité d'utiliser plusieurs trajets au travers de plusieurs VD et consolider les informations au niveau de la scène
  4. Il n'est plus nécessaire d'encoder le code d'accès à l'API SNCF. La scène le fait tout seule :60:
  5. Indication qu'il n'y a plus de trajets disponible lors de la navigation dans les trajets (inférieur à 5)
  6. Possibilité d'utiliser comme point de départ ou d'arrivée, soit un :
  • stop_points (lieu d'arrêt dans une Gare)
  • stop_areas  (lieu tel qu'une localité) c'est utile lorsqu'il y a plusieurs gares dans une localité et ne pas avoir à choisir une gare en particulier. C'est notamment pénible lorsqu'il faut choisir entre les gares TGV, Corail, RER, Francilien, ...

1) Veuillez installer le nouveau VD ci-dessous :

 

Itinéraire_SNCF.vfib.json

 

Spéciale dédicace pour @Sakkhho :13: maintenant que les codes (stop_points ou stop_areas) sont intégré dans la scène. il sera moins nécéssaire de rechercher le VD lors de mise à jours. plus de modification des boutons sur le VD et répercussion des modifications dans le code de chacun des boutons.

 

Reste néanmoins à modifier pour cette fois la variable SceneID_Traj_SNCF par l'ID de la Scène Itinéraire SNCF. Enfin, jusqu'à la prochaine livraison d'un nouveau VD.

 

2) Veuillez charger le nouveau code de la scène :

 

Il convient de :

  • modifier le contenu de la variable User_API_Sncf par votre code obtenu par mail par la SNCF. Mais cette en le laissant sans encodage 64.
  • modifier/compléter la liste des variables utilisateur :
    • VD_Id             = Id du VD de pilotage de votre Trajet
    • Traj_Titre        = Désignation du trajet pour le répéter des le mode debug
    • code_api_from = Code de votre station de départ évoqué ci-dessus
    • code_api_to     = Code de votre station d'arrivée évoqué ci-dessus
    • Msg_Sonos      = Indication si souhaitez envoyer un message sur votre Sonos
    • Volume_Sonos  = Niveau du volume du message
    • Msg_Depart     = Non en phonétique de votre point de départ, pour message Sonos
    • Msg_Arrivee     = Non en phonétique de votre point d'arrivée, pour message Sonos
  • si vous utilisez plusieurs trajets (plusieurs VD), vous devez compléter/dupliquer cette liste pour chacun des VD

 

 

3) Bons tests

 

PS : Les étapes suivantes du projet seront probablement consacré à 

  • la mixité des modes de transport entre (Trains, RER, BUS, Metro)
  • la recherche s'il y a des perturbations sur l'une des lignes utilisées par le trajet.

Si vous avez d'autres idées, vous pouvez toujours faire vos demandes ;)

 

--[[
%% properties
%% events
%% globals
--]]

----------------------------------------------------------------------------------
-- Name : HC2 SNCF Itinéraire
-- Type : Virtual Device & Scene
-- Cette scène permet d'obtenir l'horaire du prochain train au départ d'une gare
----------------------------------------------------------------------------------
-- Evolution du Projet à venir :
--   l'identification des incidents sur le trafic (retard)
--   la mixité des modes de transport entre (Trains, RER, BUS, Metro)
----------------------------------------------------------------------------------
-- Version  : 0.6
-- Création : MAM78
-- Date MAJ : 15/07/2017
--
-- Evolutions :
--   V0.1 09/07/2017 : 1) Initialisation du projet
--
--   V0.2 10/07/2017 : 1) Association de la scène à un VD qui appel la scène en
--					      passant les paramètres de la recherche d'itinéraire
--
--   V0.3 12/07/2017 : 1) Ajouts de boutons de navigation pour parcourir les diférents
--					      itinéraires par odre chronologique des départs
--
--   V0.4 13/07/2017 : 1) La décomposition du parcours sur chacune des étapes 
--                        (changements) Maximum 9 étapes pour le moment.
--                     2)  Le temps de trajet global, ainsi que par étape
--                     3)  Le mode de circulation pour chacune des étape
--                         (La ligne à utiliser, Trajet à pied, Attente en gare, ...
--					   4) La possibilité de choisir le mode retour (inversion entre
--                        le point de départ et d'arrivé).
--
--   V0.5 13/07/2017 : 1) Possibilité d'utiliser les flèches de navigation que ce
--                        soit pour un trajet Aller ou Retour
--
--   V0.6 14/07/2017 : 1) affichage d'alertes sur les retards au départ/arrivée
--                        avec la cause (si disponible)
--                     2) Consolidation de l'ensemble des paramètres des trajets
--                        dans la scène pour simplifier leur mise à jour et les
--                        rassembler à un seul et même endroit
--                     3) Possibilité d'utiliser plusieurs trajets au travers 
--                        de plusieurs VD et consolider les informations 
--                        au niveau de la scène
--                     4) Il n'est plus nécessaire d'encoder le code d'accès à
--                        l'API SNCF. La scène le fait tout seule
--                     5) Indication qu'il n'y a plus de trajets disponible 
--                        lors de la navigation dans les trajets (inférieur à 5)
--                     6) Possibilité d'ultiliser comme point de départ
--                        ou d'arrivée, soit un :
--                        - stop_points (lieu d'arrêt Gare)
--                        - stop_areas  (lieu tel qu'une localité) c'est utile
--                          lorsqu'il y a plusieurs gares dans une localité
----------------------------------------------------------------------------------

----------------------------------------------------------------------------------
-- Pour pouvoir utiliser l'API de la SNCF, vous devez vous créer un compte sur :
--    https://data.sncf.com/api
-- Une fois votre compte créé vous recevrez un mail avec une clé d’authentification
----------------------------------------------------------------------------------
local User_API_Sncf = "placé ici votre code API SNCF"

----------------------------------------------------------------------------------
-- User variables
----------------------------------------------------------------------------------
-- Les variables ci-dessous (code_api_from & code_api_to) détermine le trajet
--    que vous souhaitez utiliser
-- Ces codes sont récupérables sur le site :
--    http://canaltp.github.io/navitia-playground/play.html
-- Saisir dans champs :
--    API = https://api.sncf.com/v1
--    Token = le contenu de la variable User_API_Sncf renseigné ci-dessus
--    coverage = sncf
--    stop_points ou stop_areas = saisir le nom de votre point de départ
--        -> Votre saisie va se transformer en un code
--           Recopier ce code dans la variable code_api_from
--    stop_points ou stop_areas = saisir le nom de votre point d'arrivée
--        -> Votre saisie va se transformer en un code
--           Recopier ce code dans la variable code_api_to 
--    empty feature = departures
-- Cliquer sur le bouton SUBMIT
--    vous devriez obtenir la liste des prochains départ
----------------------------------------------------------------------------------
--  La structure Trajet ci-dessous vous permet de définir l'ensemble des trajets
--    que vous souhaitez créer. Chacune des ces structures correspond un VD
--    qui permet de piloter vos trajets. Un Trajet = Un VD
--    VD_Id ci-dessous permet de faire la correspondance avec les paramètres ci-dessous
----------------------------------------------------------------------------------
--  Description des variables :
--    VD_Id         = Id du VD de pilotage de votre Trajet
--    Traj_Titre    = Désignation du trajet pour le répérer dans en mode debug
--    code_api_from = Code de votre station de départ évoqué ci-dessus
--    code_api_to   = Code de votre station d'arrivée évoqué ci-dessus
--    Msg_Sonos     = Indication si souhaitez envoyer un message sur votre Sonos
--    Volume_Sonos  = Niveau du volume du message
--    Msg_Depart    = Non en phonétique de votre point de départ, pour message Sonos
--    Msg_Arrivee   = Non en phonétique de votre point d'arrivée, pour message Sonos
----------------------------------------------------------------------------------

local Trajets = {
    {
		["VD_Id"]         = 245,
    	["Traj_Titre"]    = "Trajet A",
		["code_api_from"] = "stop_point:OCE:SP:TrainTER-87761007",
		["code_api_to"]   = "stop_point:OCE:SP:TrainTER-87725689",
        ["Msg_Sonos"]     = "Non",
        ["Volume_Sonos"]  = 10,
        ["Msg_Depart"]    = "letan la ville",  -- écriture phonétique pour TTS
        ["Msg_Arrivee"]   = "La Défense"       -- écriture phonétique pour TTS
    },
	{
		["VD_Id"]         = 999,
    	["Traj_Titre"]    = "Trajet A",
		["code_api_from"] = "stop_area:OCE:SA:87386573",
		["code_api_to"]   = "stop_point:OCE:SP:Transilien-87382218&",
        ["Msg_Sonos"]     = "Non",
        ["Volume_Sonos"]  = 10,
        ["Msg_Depart"]    = "letan la ville",  -- écriture phonétique pour TTS
        ["Msg_Arrivee"]   = "La Défense"       -- écriture phonétique pour TTS
	}
	}

local modetrace = true
local modedebug = true

----------------------------------------------------------------------------------
-- Ne pas modifier le code ci-dessous, sinon pour l'adapter à votre usage
----------------------------------------------------------------------------------
local TimeOut = 3000
----------------------------------------------------------------------------------
-- Message pour mode Trace
----------------------------------------------------------------------------------
function Trace(color, message)
	if modetrace then 
        if color and color ~= "" then
            fibaro:debug('<span style="color:'..color..';">'..message..'</span>')
        else
            fibaro:debug(message)
        end
	end
end

----------------------------------------------------------------------------------
-- Message pour mode Debug
----------------------------------------------------------------------------------
function Debug(color, message)
	if modedebug then 
        if color and color ~= "" then
            fibaro:debug('<span style="color:'..color..';">'..message..'</span>')
        else
            fibaro:debug(message)
        end
    end
end

function SetUI(id, target, value)
  fibaro:call(id, "setProperty", "ui."..target..".value", value);
end

function SetUI_label(id, target, value)
  fibaro:call(id, "setProperty", "ui."..target..".label", value);
end

----------------------------------------------------------------------------------
-- encoding to base64 
----------------------------------------------------------------------------------
-- character table string 

-- encoding to base64 
function encode64(data) 
   local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 
   return ((data:gsub('.', function(x) 
       local r,b='',x:byte() 
       for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end 
       return r; 
   end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) 
       if (#x < 6) then return '' end 
       local c=0 
       for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end 
       return b:sub(c+1,c+1) 
   end)..({ '', '==', '=' })[#data%3+1]) 
end 
----------------------------------------------------------------------------------
-- Retourne le jour de la semaine en clair
----------------------------------------------------------------------------------
function josdGetJourSemaine(jour)
	josdGetJourSemaineTab={[0]="Dimanche",[1]="Lundi",[2]="Mardi",[3]="Mercredi",[4]="Jeudi",[5]="Vendredi",[6]="Samedi"}
	return josdGetJourSemaineTab[tonumber(jour)]
end

----------------------------------------------------------------------------------
-- Conversion un nombre de seconde en texte xhxmin ou xmin
----------------------------------------------------------------------------------
function Conversion_Seconde_en_Texte(NbSec)
  
  local NbH=math.floor(NbSec/60/60)
  NbSec = NbSec - NbH * 60 * 60
  local NbM=math.floor(NbSec/60)
  NbSec = NbSec - NbH * 60
  if NbH > 0 then
    return NbH.."h"..NbM.."min"
  else
    return NbM.."min"
  end
end

----------------------------------------------------------------------------------
-- Conversion format date "aaaammjjThhmmss" en format date
----------------------------------------------------------------------------------
function Conversion_Date(dateheure)

    local TableDate = os.date("*t")
    TableDate.day = string.sub (dateheure, 7, 8)
    TableDate.month = string.sub (dateheure, 5, 6)
    TableDate.year = string.sub (dateheure, 1, 4)
    TableDate.hour = string.sub (dateheure, 10, 11)
    TableDate.min = string.sub (dateheure, 12, 13)
    return (os.time(TableDate))
end

function Effacement_Data()

    SetUI(VD_Id, "lblFromTo", "")
    SetUI(VD_Id, "lblDepArr", "")
    SetUI(VD_Id, "lblNum", "")
    SetUI(VD_Id, "lblTraficDepart", "")
    SetUI(VD_Id, "lblTraficArrivee", "")
  
    for i = 1, 9 do
      SetUI(VD_Id, "lblIti"..i, " ")
    end
 
end

function Traitement_Retard(Status, Perturbations, First_stop_point, Last_stop_point)

  Debug("grey","First_stop_point="..First_stop_point)
  Debug("grey","Last_stop_point="..Last_stop_point)
  
  Debug("grey","Status=".."*"..Status.."*")
  
  if Status == "" then
    SetUI(VD_Id, "lblTraficDepart", "RAS")
    SetUI(VD_Id, "lblTraficArrivee", "RAS") 
  else
    SetUI(VD_Id, "lblTraficDepart", "")
	SetUI(VD_Id, "lblTraficArrivee", "")
    if Status == "SIGNIFICANT_DELAYS" then
      
      local Perdu_Lib_Depart = ""
      local Perdu_Lib_Arrivee = ""
      for Num_Pertu = 1 , #Perturbations do

        Debug("grey", "Trace 1 / status="..Perturbations[Num_Pertu].status.." / "..Perturbations[Num_Pertu].cause)
        
        SetUI(VD_Id, "lblTraficCause", Perturbations[Num_Pertu].cause)
        
        local impacted_objects = Perturbations[Num_Pertu].impacted_objects
        
        Debug("grey", "Trace 2 / impacted_objects ="..#impacted_objects)
        
        for Num_impacted_objects = 1 , #impacted_objects do
         
          local impacted_stops = impacted_objects[Num_impacted_objects].impacted_stops
          
          Debug("grey", "Trace 3 / impacted_stops ="..#impacted_stops)
          
          for Num_impacted_stops = 1 , #impacted_stops do
            
            local stop_point = impacted_stops[Num_impacted_stops].stop_point
            
            Debug("grey", "Trace 4 / stop_point ="..Num_impacted_stops)
            
            Debug("grey", "Trace 5 / First_stop_point=".."*"..First_stop_point.."*")
            Debug("grey", "Trace 6 / First_stop_point=".."*"..stop_point.id.."*")
            
            if stop_point.id == First_stop_point then
              Debug("grey","Trouve First_stop_point="..stop_point.id)
              if impacted_stops[Num_impacted_stops].departure_status == "delayed" then
                Perdu_Lib_Depart = Conversion_Seconde_en_Texte(tonumber(impacted_stops[Num_impacted_stops].amended_departure_time) - tonumber(impacted_stops[Num_impacted_stops].base_departure_time))
                SetUI(VD_Id, "lblTraficDepart", "Retard de "..Perdu_Lib_Depart)
              end
              break
            end
          end  
          for Num_impacted_stops = 1 , #impacted_stops do
            
            local stop_point = impacted_stops[Num_impacted_stops].stop_point
            
            Debug("grey", "Trace 7 / stop_point ="..Num_impacted_stops)
            
            Debug("grey", "Trace 5 / Last_stop_point=".."*"..Last_stop_point.."*")
            Debug("grey", "Trace 6 / Last_stop_point=".."*"..stop_point.id.."*")
            
            if stop_point.id == Last_stop_point then
              Debug("grey","Trouve Last_stop_point="..stop_point.id)
              if impacted_stops[Num_impacted_stops].departure_status == "delayed" then
                Perdu_Lib_Arrivee = Conversion_Seconde_en_Texte(tonumber(impacted_stops[Num_impacted_stops].amended_arrival_time) - tonumber(impacted_stops[Num_impacted_stops].base_arrival_time))
              end
              break
            end
          end  
        end
      end

      if Perdu_Lib_Depart == "" then
        SetUI(VD_Id, "lblTraficDepart", "RAS")
      else
        SetUI(VD_Id, "lblTraficDepart", "Retard de "..Perdu_Lib_Depart)
      end
      if Perdu_Lib_Arrivee == "" then
        SetUI(VD_Id, "lblTraficArrivee", "RAS")
      else
        SetUI(VD_Id, "lblTraficArrivee", "Retard de "..Perdu_Lib_Arrivee)
      end
    else
      SetUI(VD_Id, "lblTraficDepart", Status)
    end
  end
 
  
end

function Affiche_Iti(Sections, Status, Perturbations, Traj_Num)

  local Last_PT = nil
    
  local Max_Nb_Iti= 0
  
  local Nb_Iti = 0
   
  if #Sections > 9 then
    Max_Nb_Iti = 9
  else
    Max_Nb_Iti = #Sections
  end

  Debug("grey","Nb_Section, Max_Nb_Iti="..#Sections..", "..Max_Nb_Iti)
  
  local First_stop_point = ""
  local Last_stop_point = ""
  
  for Num_Iti = 1 , Max_Nb_Iti do
      
      local Itineraire = Sections[Num_Iti]
    
      if Itineraire.type == "waiting" then
        Debug("grey","Traitement Trajet-Itinéraire, type : "..Traj_Num.."-"..Num_Iti.." ,"..Itineraire.type)
      else
        Debug("grey","Traitement Trajet-Itinéraire, type, embedded_type : "..Traj_Num.."-"..Num_Iti.." ,"..Itineraire.type.." , "..Itineraire.to.embedded_type)
	  end
    
      if Itineraire.type == "public_transport" then
        Last_PT = Num_Iti
      end
      
      local Date_Time = Conversion_Date(Itineraire.departure_date_time)              
        
      local Lbl_message = "("..Conversion_Seconde_en_Texte(tonumber(Itineraire.duration))..")"
        
      local Date_Time = Conversion_Date(Itineraire.arrival_date_time)
      Lbl_message = Lbl_message.." -> "..os.date("%H:%M", Date_Time)
  
      if Itineraire.type == "waiting" then
        Lbl_message = Lbl_message.." à " ..Der_Dest
        Lbl_message = Lbl_message.." -> " .."[En ATTENTE]"
      elseif Itineraire.type == "walking" then
        if Itineraire.to.embedded_type == "stop_point" then	
          Der_Dest = Itineraire.to.stop_point.name
          Last_stop_point = Itineraire.to.stop_point.id
          if First_stop_point == "" then
          	First_stop_point = Itineraire.from.stop_point.id
          end
        else
          Der_Dest = Itineraire.to.stop_area.name
        end
        Lbl_message = Lbl_message.." à " ..Der_Dest
        Lbl_message = Lbl_message.." -> " .."[à PIED]"
      elseif Itineraire.type == "transfer" then
        if Itineraire.transfer_type == "walking" then
          if Itineraire.to.embedded_type == "stop_point" then	
            Der_Dest = Itineraire.to.stop_point.name
            Last_stop_point = Itineraire.to.stop_point.id
            if First_stop_point == "" then
              First_stop_point = Itineraire.from.stop_point.id
            end
          else
            Der_Dest = Itineraire.to.stop_area.name
          end
          Lbl_message = Lbl_message.." à " ..Der_Dest
          Lbl_message = Lbl_message.." -> " .."[à PIED]"
        end
      elseif Itineraire.type == "crow_fly" then
        if Itineraire.mode == "walking" then
          if Itineraire.to.embedded_type == "stop_point" then	
            Der_Dest = Itineraire.to.stop_point.name
            Last_stop_point = Itineraire.to.stop_point.id
            if First_stop_point == "" then
              First_stop_point = Itineraire.from.stop_point.id
            end
          else
            Der_Dest = Itineraire.to.stop_area.name
          end
          Lbl_message = Lbl_message.." à " ..Der_Dest
          Lbl_message = Lbl_message.." -> " .."[à PIED]"
        end
      else
      	if Itineraire.to.embedded_type == "stop_point" then	
          Der_Dest = Itineraire.to.stop_point.name
          Last_stop_point = Itineraire.to.stop_point.id
          if First_stop_point == "" then
          	First_stop_point = Itineraire.from.stop_point.id
          end
        else
          Der_Dest = Itineraire.to.stop_area.name
        end
        Lbl_message = Lbl_message.." à " ..Der_Dest
        Lbl_message = Lbl_message.." ["..Itineraire.display_informations.commercial_mode .." / "..Itineraire.display_informations.code.."]"
      end

    if tonumber(Itineraire.duration) == 0 then
      Max_Nb_Iti = Max_Nb_Iti -1
    else
      Nb_Iti = Nb_Iti + 1
      SetUI(VD_Id, "lblIti"..Nb_Iti, Lbl_message)
    end
  end
  
  
  if Nb_Iti < 9 then
    for i = Nb_Iti + 1, 9 do
      SetUI(VD_Id, "lblIti"..i, " ")
    end
  end
  
  SetUI(VD_Id, "lblFromTo", fibaro:get(VD_Id, "ui.lblFromTo.value").. " -> " ..Der_Dest)
  
  -------------------------------------------------------------------------------
  -- Traitement des retards
  -------------------------------------------------------------------------------
  Traitement_Retard(Status, Perturbations, First_stop_point, Last_stop_point)
    
  return Der_Dest
  
end

function Affiche_Traj(data)
  
  local Traj_Num = tonumber(string.sub(fibaro:get(VD_Id, "ui.lblNum.value"), -1))

  local Trajet = data.journeys
  
  if #Trajet < Traj_Num then
    
  	local Traj_Text = fibaro:get(VD_Id, "ui.lblNum.value")
    local Traj_Sens = string.sub(Traj_Text, 1, 1)
    
    Effacement_Data()
              
    SetUI(VD_Id, "lblDepArr", "Plus de trajets disponibles")
    
	Traj_Num = Traj_Num - 1

    if Traj_Sens == "A" then
      fibaro:call(VD_Id, "setProperty", "ui.lblNum.value", "Aller N° "..Traj_Num)
    else
      fibaro:call(VD_Id, "setProperty", "ui.lblNum.value", "Retour N° "..Traj_Num)
    end
    
    Der_Dest = ""
    
  else
  
    Trace("blue","Traitement Trajet : "..Traj_Num)
    
    if data.journeys[Traj_Num].sections[1].from.embedded_type == "stop_point" then
        SetUI(VD_Id, "lblFromTo", data.journeys[Traj_Num].sections[1].from.stop_point.name)
    else
        SetUI(VD_Id, "lblFromTo", data.journeys[Traj_Num].sections[1].from.stop_area.name)
    end
  
    local Date_Time = Conversion_Date(data.journeys[Traj_Num].departure_date_time)              
      
    local Lbl_message = "à "..os.date("%H:%M", Date_Time)
      
    local Date_Time = Conversion_Date(data.journeys[Traj_Num].arrival_date_time)              
        
    Lbl_message = Lbl_message .." -> "..os.date("%H:%M", Date_Time).." ("..Conversion_Seconde_en_Texte(tonumber(data.journeys[Traj_Num].duration))..")"
    
    SetUI(VD_Id, "lblDepArr", Lbl_message)
  
    local Der_Dest = Affiche_Iti(data.journeys[Traj_Num].sections, data.journeys[Traj_Num].status, data.disruptions, Traj_Num)
  
  end
  
  return Der_Dest

end
----------------------------------------------------------------------------------
-- Traitement des données en provenance de l'IPA SNCF
----------------------------------------------------------------------------------
function GetData()

  Debug("grey","T1".." - "..Traj_Titre)
  local api_url = "https://api.sncf.com/v1"
  local api_coverage = "sncf"
  local api_fonction = "journeys?"
  
  local Traj_Sens = string.sub(fibaro:get(VD_Id, "ui.lblNum.value"), 1, 1)

  local api_from = ""
  local api_to = ""
  
  if Traj_Sens == "A" then
    api_from = code_api_from
    api_to = code_api_to
  else
    api_from = code_api_to
    api_to = code_api_from
  end
  
  local api_datetime = os.date("%Y%m%dT%H%M00", os.time())
  local api_datetime_represents = "departure"
  local api_min_nb_journeys = "5"

  local Query = api_url
  local Query = Query .. "/coverage/" .. api_coverage
  local Query = Query .. "/" .. api_fonction
  local Query = Query .. "from=" .. api_from.."&"
  local Query = Query .. "to=" .. api_to.."&"
  local Query = Query .. "datetime=" .. api_datetime.."&"
  local Query = Query .. "datetime_represents=" .. api_datetime_represents.."&"
  local Query = Query .. "min_nb_journeys=" .. api_min_nb_journeys
  
  Debug("grey","T2".." - "..Traj_Titre)
    
  local http = net.HTTPClient({ timeout = TimeOut })
  
  Debug("grey","T3".." - "..Traj_Titre)
  
  Debug("grey",Query)
  
  local ok = pcall(function() http:request(Query, {
      options = { 
        method = 'GET', 
        headers ={
              ["Content-Type"] = "application/json",
              ["Authorization"] = "BASIC "..User_API_Sncf_Encode64},           
        data = body
        },
      
      success = function(response)
            
        Debug("grey","T4".." - "..Traj_Titre)
              
	    if response.status == 200 then
          
          Debug("grey","T5".." - "..Traj_Titre)
          Trace("blue","Traitement ok : "..Traj_Titre)
          local status, data = pcall(json.decode, response.data)
            
          if (status and data) then
                
            local Der_Dest = Affiche_Traj(data)
            
            if Der_Dest == "" then
	          Debug("grey","Plus de trajet à afficher")
            else
                  
              if data.journeys[1].sections[1].from.embedded_type == "stop_point" then	
                  Trace("green","Départ : "..data.journeys[1].sections[1].from.stop_point.name)
              else
                  Trace("green","Départ : "..data.journeys[1].sections[1].from.stop_area.name)
              end 
              Trace("green","Direction : "..Der_Dest) 
                                  
              local Date_Time = Conversion_Date(data.journeys[1].sections[1].departure_date_time)              
              local Horaire = tostring(tonumber(os.date("%H", Date_Time))) .. " heure ".. tostring(tonumber(os.date("%M", Date_Time)))
              local JourSemaine = josdGetJourSemaine(os.date("%w", MonHeure))
                  
              -- Test pour vérifier si le prochain départ est pour le jour même
              if os.date("%Y/%m/%d",Date_Time) == os.date("%Y/%m/%d",time) then
                Prochain_Depart = "aujourd'hui"
              else
                Prochain_Depart = JourSemaine
              end
                  
              Trace("green", "Prochain départ "..Prochain_Depart.." à " ..os.date("%H:%M", Date_Time))
  
              message = "Prochain départ"
              message = message .. " "..Prochain_Depart
              message = message .. " de "..Msg_Depart
              message = message .. " pour "..Msg_Arrivee
              message = message .. " a ".. Horaire
                    
              local Date_Time = Conversion_Date(data.journeys[1].sections[1].arrival_date_time)              
              local Horaire = tostring(tonumber(os.date("%H", Date_Time))) .. " heure ".. tostring(tonumber(os.date("%M", Date_Time)))
              local JourSemaine = josdGetJourSemaine(os.date("%w", Date_Time))
                  
              message = message .. " Arrivée à "..Horaire
                  
              Trace("green", "Arrivée à " ..os.date("%H:%M", Date_Time))
                                  
              -- Envoi d'un message sur l'enceinte SONOS
              if Msg_Sonos == "OUI" then    
                Debug("grey", "Envoi Message sur enceinte SONOS")
                    
                fibaro:startScene(SceneID_Sonos, {{msg = message}, {vol = Volume_Sonos}})
              end                
            end    
          else
            Trace("orange"," Attention : Aucunes données à traiter")
            
            Effacement_Data()
              
            SetUI(VD_Id, "lblDepArr", "Erreur =".."aucune données")
          end
        else
          Debug("grey","T6".." - "..Traj_Titre)
              
          Trace("yellow","Traitement ko : "..Traj_Titre)
          
          Effacement_Data()
              
          SetUI(VD_Id, "lblDepArr", "Erreur ="..response.status)
              
          if response.status == 500 or response.status == 503 then
            Trace("orange","Erreur d'indisponibilité du serveur")
          else
            Trace("orange","Erreur requête serveur, response.status = "..response.status)
          end    
        end
      end,
      
      error = function(err)
        Debug("grey","T7".." - "..Traj_Titre)
        Trace("orange","Erreur de reception de données, Erreur = ".. err)
        Effacement_Data()
              
        SetUI(VD_Id, "lblDepArr", "Erreur ="..err)
      end
  })
  
  end)
  if not(ok) then
    Trace("orange","Erreur dans l'exécution de fhttp:request(Query")
  end
  Debug("grey","T9".." - "..Traj_Titre)

end
  
function Start()

  Debug("grey","VD_Id="..VD_Id.." / Volume_Sonos="..Volume_Sonos.." / Msg_Sonos="..Msg_Sonos)

  -- test pour vérifier si le module virtuel exist ou pas
  local ip = fibaro:get(VD_Id, 'IPAddress')
  if ip == nil then
    Debug("orange","Warning : Le module virtuel : "..VD_Id.." n'existe pas. Vous devez le créer !")
  else
    -- Lancement du traitement de l'itinéraire
    GetData()
  end
end


-------------------------------------------------------------------------------
-- Begining off Scène
-------------------------------------------------------------------------------
local params = fibaro:args()

Trace("orange","Début de traitement de la scène")

if (params) then

  for k, v in ipairs(params) do

    if (v.VD_Id) then VD_Id = v.VD_Id end

  end
  
  local Trouve_VD_Id = false
  
  for i = 1, #Trajets do
    if VD_Id == Trajets[i].VD_Id then
      Debug("grey","VD_Id="..VD_Id.." ("..fibaro:getName(VD_Id)..") a bien été trouvé")

      Traj_Titre    = Trajets[i].Traj_Titre
      code_api_from = Trajets[i].code_api_from
      code_api_to   = Trajets[i].code_api_to
      Msg_Sonos     = Trajets[i].Msg_Sonos
      Volume_Sonos  = Trajets[i].Volume_Sonos
      Msg_Depart    = Trajets[i].Msg_Depart
      Msg_Arrivee   = Trajets[i].Msg_Arrivee
      Trouve_VD_Id = true
      break
    end
  end
  
  User_API_Sncf_Encode64 = encode64(User_API_Sncf)
  if Trouve_VD_Id then
    Start()
  else
    Trace("orange","Erreur : Votre VD n'a pas été trouvé dans le tableau Trajets")
  end
else
  Trace("orange","Erreur : Cette scène fonctionne par appel depuis un VD avec un passage de paramètres")
end

Trace("orange","Fin de traitement de la scène")

 

Modifié par MAM78
  • Upvote 2
Posté(e)

c'est installé. tout fonctionne

 

pas certains comment est géré l'indication de retard sur les RER. on verra

je garde mon VD en parallèle pour le moment

Posté(e) (modifié)

tu devrais gérer la gestion ds icônes en fonction de l'état trafic (demain) ou moins pour le moment pour éviter de devoir les remettre à la main :)à

local virtualDeviceId = 310
local TraficOk = 1121
local TraficNok = 1122

 fibaro:call(virtualDeviceId , "setProperty", "currentIcon", TraficOk)

meme si je sais que tu as pas besoin d'aide lol , je me sens utile :-)

Modifié par Sakkhho
Posté(e)

C'est bon j'ai intégré les icônes paramétrables.

 

Ce sera dispo. dans la prochaine MAJ.

 

Mais du coup, il faudra repasser par un chargement de VD ;)

 

Posté(e)
Il y a 20 heures, MAM78 a dit :

Voici une nouvelle version 0.6

 

Et bien on dirait que tout est OK

 

sncf10.thumb.JPG.90f219a28cb5d98808541c0c48aecafd.JPG

 

 

Crois tu qu'il est possible d'ajouter le N° du TER ex : TER n°17816   ...?

 

Screenshot_2017-07-15-20-29-08.thumb.png.06679aae33d5030bbfcd062f5aaebecf.png

 

 

Et comment faire pour la notification , une idée ?

 

 

Merci

Posté(e)

Merci pour ce test et cette confirmation du bon fonctionnement des retards dans les trajets.

 

J'ai ajouté comme demandé le n° de train (voir ci-dessous). Ce sera disponible dans la prochaine version.

 

Cette nouvelle version va également apporter la possibilité de se connecter à une autre base API (api.navitia.io) qui contient les lignes de Metro et de Bus (mais sans les indication sur les retards, dommage).

 

596a667f9bb9b_Sanstitre9.thumb.png.cb0ab92852c015f6775618b90ae0f00c.png

Posté(e)

un petit avant gout d'un itinéraire utilisant le train et le métro avec un peu de marche entre les stations ;)

 

596a6d5150083_Sanstitre9.thumb.png.b77d6f7059110d7c6157dabf7a621dba.png

Posté(e)
il y a une heure, MAM78 a dit :

J'ai ajouté comme demandé le n° de train (voir ci-dessous). Ce sera disponible dans la prochaine version.

Tip Top une fois de plus,

 

Et à ton avis pour les notifications , c 'est koi le plus pertinents ..?

Posté(e)

Pour ce faire il faut programmer une mise à jour du VD (clic sur le premier bouton) à un moment précis qui précède l'heure de départ théorique du train que l'on veut prendre.

Sinon si l'on actualise régulièrement le VD, nous seront pollué par des messages (dès lors qu'un trajet présente un retard).

 

Je suis entrain de regarder la possibilité de définir une fonction qui permettrait de rechercher un prochain trajet à partir d'un horaire précis qui serait paramétrable.

Et dans ce cas il n'y aurait plus de risque de pollution de message et il serait donc possible à tout moment de faire la recherche. Par exemple dès la veille.

 

Après, il conviendra de déterminer le mode d'envoi des messages (mail, sms, notification, TTS, ...) 

 

×
×
  • Créer...