Skip to content

Instantly share code, notes, and snippets.

@mqu
Forked from anonymous/tisseo.rb
Last active May 15, 2024 13:40
Show Gist options
  • Save mqu/cccbba03a4c1a4119176 to your computer and use it in GitHub Desktop.
Save mqu/cccbba03a4c1a4119176 to your computer and use it in GitHub Desktop.
classe Ruby permettant l'accès à l'API TISSEO

TISSEO API for Ruby Language

Vous trouverez sur ce site, une interface (API) de programmation en langage Ruby pour adresser le Webservice TISSEO. Ce travail est en cours de réalisation (Work in progress). Soyez donc indulgents.

mots clés : TISSEO, API, REST, Ruby, Webservices, transport, metro, Toulouse.

#Introduction

Ceci est un ensemble de classes Ruby permettant d'interroger l'API Tisséo.

Tisséo est la marque commerciale du réseau de transports en commun de Toulouse et sa région.

Tisséo publie sur un [serveur dédié] (https://api.tisseo.fr/) des données permettant de réaliser des applications liées aux transports en commun. Ces données sont publiées sous forme de web-services et sont interrogeables en s'appuyant sur le format REST.

L'API est abondament décrite sur le site open-data de la métropôle toulousaine. Cette initiative s'incrit dans le mouvement Open Data pour laquelle, la communauté urbaine de Toulouse est partie prenante.

L'API Tisséo possède les caractéristiques suivantes :

  • l'API est versionnée ; la version en cours au 11/2015 est la v1
  • les requetes se font généralement avec un GET, via le protocole REST,
  • afin d'interroger le serveur, vous devrez demander une clé d'accès (*5). Elle se présente sous cette forme : 'xxxxxxxx-yyyy-zzzz-kkkk-vvvvvvvvvvvv' ; cette clé vous sera confiée à titre privé. Vous prendrez soin de lire le chapitre 2.2 et suivant, concernant les conditions d'utilisation de l'API,
  • l'API délivre des données statiques (lignes, arrets, horaires de passage des bus) et des données temps-réel : horaire estimé d'arrivée des bus.
  • En plus de l’API temps réel, Tisséo fourni des fichiers descriptifs de son offre transport sur le portail OpenData de Toulouse Métropole. Ces fichiers sont disponibles aux formats standard Trident et GTFS sous la même licence ODBL (voir paragraphe 2.4 de l'API).

#Installation

  • sur machine Debian (et Ubuntu) : apt-get install ruby ruby-rest-client ruby-json
  • ce code a été testé avec la version 2.1 de Ruby.

#Configuration

#Utilisation

sauf utilisation spécifique, on pourra utiliser l'API simplifiée TisseoRestful qui simplifie l'accès aux données et permet de filtrer simplement les résultats.

API Tisseo au format Restful

  • le premier mot clé correspond à un commande
  • les mots clés suivants permettent le filtrage, généralement, dans un sous-ensemble

ex :

   
   require 'tisseo.rb'
   
   rest = TisseoRest.new ...
   tisseo=TisseoRestful.new rest

   tisseo.get '/networks'             # liste tous les réseaux
   tisseo.get '/networks/tisseo       # sélectionne le réseau Tisseo

   tisseo.get '/places/<expr>'        # tous les lieux liés à <expr>
   tisseo.get '/places/city/<expr>'   # filtre uniquement les villes (city)
   tisseo.get '/places/road/<expr>'   # filtre uniquement les noms de rues (road)
 
   tisseo.get '/lines'                # toutes les lignes (TISSEO)
   tisseo.get '/line/57'              # la ligne 57
   tisseo.get '/line/57/mounède'      # arrêt Mounède sur la ligne 57
   tisseo.get '/line/57/mounede/next' # prochains passages sur arret mounêde / ligne 57

Notes :

  • l'API Tisséo supporte les caractères accentués au format UTF8,
  • d'autre part, un mécanisme de cache local a été mis en place et permet de réduire considérablement l'accès au serveur de données TISSEO.
  • la classe ruby Tisseo actuelle impose :
    • des résultats en anglais (:en)
    • s'appuie sur la version 1.0 de l'API. Cette API peut évoluer dans le temps.

#Classes et méthodes

class Rest
	def get url, args
class RestCache < Rest
	def initialize
	def md5 url, args
	def file url, args
	def file_age path
	def get url, args
class TisseoRest < RestCache
	def initialize key, api='https://api.tisseo.fr', version='v1'
	def opts
	def get cmd, args={}, format='json'
class Tisseo
	def initialize rest
	def get	cmd, args={}, format='json'
class TisseoRestful < Tisseo
	def get arg

#Liens

#!/usr/bin/ruby -w
# coding: UTF-8
=begin
API TISSEO pour le langage Ruby
auteur : Marc Quinton / décembre 2015 ; licence MIT
version : 0.3 ; toute contribution est bienvenue.
url:https://gist.github.com/mqu/cccbba03a4c1a4119176
key-words: toulouse, tisseo, ruby, rest
Tisséo est la marque commerciale du réseau de transports en commun de Toulouse et sa région.
Tisséo publie sur un serveur dédié (*1) des données permettant de réaliser
des applications liées aux transports en commun. Ces données sont publiées sous forme
de web-services et sont interrogeables en s'appuyant sur le format REST (*2).
L'API est abondament décrite sur le site (*3).
Cette initiative s'incrit dans le mouvement Open Data pour laquelle, la communauté urbaine
de Toulouse est partie prenante (*4).
L'API Tisséo possède les caractéristiques suivantes :
- l'API est versionnée ; la version en cours au 11/2015 est la v1
- les requetes se font généralement avec un GET, via le protocole REST,
- afin d'interroger le serveur, vous devrez demander une clé d'accès (*5). Elle se présente sous
cette forme : 'xxxxxxxx-yyyy-zzzz-kkkk-vvvvvvvvvvvv' ; cette clé vous sera confiée à titre
privé. Vous prendrez soin de lire le chapitre 2.2 et suivant, concernant les conditions
d'utilisation de l'API,
- l'API délivre des données statiques (lignes, arrets, horaires de passage des bus) et des
données temps-réel : horaire estimé d'arrivée des bus.
- En plus de l’API temps réel, Tisséo fourni des fichiers descriptifs de son offre transport sur le portail
OpenData de Toulouse Métropole. Ces fichiers sont disponibles aux formats standard Trident et GTFS sous
la même licence ODBL (voir paragraphe 2.4 de l'API).
Voici les URL pour récupérer ces fichiers :
Format GTFS : https://data.toulouse-metropole.fr/explore/dataset/tisseo-gtfs/?tab=metas
Format Trident : https://data.toulouse-metropole.fr/explore/dataset/tisseo-offre-de-transport-neptune/?tab=table
spécifications format GTFS : https://developers.google.com/transit/gtfs/
spécifications format Trident : http://www.predim.org/spip.php?article1087
spécification du format Neptune : http://www.normes-donnees-tc.org/category/neptune/
La classe Ruby Tisseo ci-dessous permet d'accéder à l'API Tisseo.
require 'pp'
require 'json'
require 'rest-client'
require 'tisseo.rb'
key='xxxxxxxx-yyyy-zzzz-kkkk-vvvvvvvvvvvv'
tisseo = Tisseo.new key
cmd='stop_points'
params = {
:stopAreaId => 1970324837184808,
:displayLines => 1,
:LineId =>11821949021891652
}
pp tisseo.get cmd, params
Configuration :
vous pourrez placer un fichier de configuration dans votre HOME de cette forme :
#!/usr/bin/ruby -w
# coding: UTF-8
# in $HOME/.config/tisseo.rb
class Tisseo
def self.config
return {
:key => 'xxxxxxxx-yyyy-zzzz-kkkk-vvvvvvvvvvvv'
}
end
end
lien :
1 : https://api.tisseo.fr/
2 : https://fr.wikipedia.org/wiki/Representational_State_Transfer
3 : https://data.toulouse-metropole.fr/explore/dataset/api-temps-reel-tisseo/?tab=table
4 : https://data.toulouse-metropole.fr/explore/dataset/api-temps-reel-tisseo/
5 : contact[arobase]tisseo.fr
autres liens :
- http://www.gtfs-data-exchange.com/agency/tisso/
- plan interractif : http://www.tisseo.fr/plan-interactif/
- https://github.com/cyounes/cyounes.github.io/tree/master/projects/tisseo-api.net
- Chouette : http://www.chouette.mobi/pourquoi-chouette/ ; https://github.com/afimb/chouette2
=end
require 'pp'
require 'json'
require 'rest-client'
class Hash
#pass single or array of keys, which will be removed, returning the remaining hash
def remove!(*keys)
keys.each{|key| self.delete(key) }
self
end
#non-destructive version
def remove(*keys)
self.dup.remove!(*keys)
end
end
# REST client based on RestClient class
class Rest
def get url, args
# printf("Rest::get(%s)\n", url) ; pp args
RestClient.get url, {:params => args}
end
end
# file cache for REST requests
class RestCache < Rest
def initialize
@opts={ :cache => {}}
@opts[:cache][:keep]=24*2 # how long to keep files in cache (in hours)
end
# compute an MD5sum hash from both url and args.
def md5 url, args
md5 = Digest::MD5.new
md5 << url
md5 << args.to_json
md5.hexdigest
end
# filename is in $HOME/.cache/tisseo
# and name is based on a MD5 hash on url+args
def file url, args
sprintf('%s/.cache/tiseo/%s', ENV['HOME'], md5(url, args))
end
# age in hours for file.
def file_age path
(Time.now - File.stat(path).mtime).to_i / 60.0
end
# add args[:cache]=false to avoid cache functionality.
def get url, args
# bypass cache if requested
if args.key? :cache # && args[:cache] == false
args.remove! :cache
return super url, args
end
# what is file name ($HOME/.config/tisseo/<hash>)
file=self.file url, args
if File.exist?(file) && (self.file_age(file)<@opts[:cache][:keep])
IO.read file
else
# create cache dir if it does not exists
dir=File.dirname(file)
Dir.mkdir dir unless File.directory? dir
# get page content and cache it to file.
content = super url, args
IO.write file, content
return content
end
end
end
class TisseoRest < RestCache
def initialize key, api='https://api.tisseo.fr', version='v1'
super()
@key=key
@api=api
@version=version
@opts[:lang] = :en
@opts[:network] = 'Tisséo' # default network
@supported_commands = [
:stop_areas, # 4.2 - p14
:stop_points, # 4.3 - p16
:places, # 4.4 - p18
:networks, # 4.5 - p22 - réseau supportés ; actuellement uniquement Tisséo
:lines, # 4.6 - p23
:stops_schedules, # 4.7 - p26
:rolling_stocks, # 4.8 - p30
:journeys, # 4.9 - p31
:messages, # 4.10 - p36 - message de service
:service_density # 4.11 - p38
]
end
def opts
@opts
end
def get cmd, args={}, format='json'
raise "TISSEO unsupported command '#{cmd.to_s}'" unless @supported_commands.include? cmd.to_sym
args[:key]=@key
args[:lang]=@opts[:lang]
url="#{@api}/#{@version}/#{cmd.to_s}.#{format}"
res = super url, args
JSON::parse res
end
end
class Tisseo
def initialize rest
@rest=rest
end
# cache opt allow to bypass cache functionality
def get cmd, args={}, format='json'
@rest.get cmd, args, format
end
end
# API Tisseo au format Restful
# - le premier mot clé correspond à un commande
# - les mots clés suivants permettent le filtrage, généralement, dans un sous-ensemble
# ex :
#
# rest = rest = TisseoRest.new ...
# tisseo=TisseoRestful.new rest
#
# tisseo.get '/networks' -> liste tous les réseaux
# tisseo.get '/networks/tisseo -> selectionne le réseau Tisseo
#
# tisseo.get '/places/<expr>' -> tous les lieux liés exp
# tisseo.get '/places/city/<expr>' -> filtre uniquement les villes (city)
# tisseo.get '/places/road/<expr>' -> filtre uniquement les noms de rues
#
# tisseo.get '/lines' -> toutes les lignes (TISSEO)
# tisseo.get '/line/57' -> la ligne 57
# tisseo.get '/line/57/mounede' -> l'arret Mounede sur la ligne 57
# tisseo.get '/line/57/mounede/next' -> prochains passages sur l'arret mounede / ligne 57
#
class TisseoRestful < Tisseo
=begin
API XPATH like
/networks
/networks/tisseo
/networks/<regexp>
/messages
/messages/level/<level> # filtrage par niveau d'importance (normal, important)
/messages/scope/[line|event|global] # filtrage par niveau d'importance
/message/type/[traffic|...]
/message/line/<regexp> # selectionne les messages attachés à une ligne
/message/name/<expr>
/message/title/<expr>
/message/message/<expr>
/message/id/<id>
/places/<name>
/places/<name>/stop
/places/<name>/road
/places/<name>/public_place
/places/city/<name> #filtrage par ville
/place/type/<name> # filtrage par type church, mail, administration ...
/lines # liste toutes les lignes
/line/57 # liste (les stop-points) de la ligne 57
/line/57/rose # liste les points d'arrets ou stop_area, de point Rose / 57
/line/57/rose/1 # selectionne le premier de la liste des arrets.
/line/57/rose/next # prochains passages à l'arret 57/roses
/line/id/xxxx # filtrage par l'id de ligne
=end
def get arg
case arg
when /\/networks\/tiss[ée]o$/i
super(:networks)['networks'].select{ |v| pp v['name']=~/tiss[ée]o/i}
when /\/networks\/(.+)$/
super(:networks)['networks'].select{ |v| v['name']=~/$1/i}
when /\/networks\/*$/
super(:networks)
when /\/messages\/*$/
super :messages
when /\/messages\/level\/(.*)/ # normal, important
super(:messages)['messages'].select{|v| v['message']['importanceLevel']==$1}
when /\/messages\/scope\/(.*)/ # global, event, line
super(:messages)['messages'].select{|v| v['message']['scope']==$1}
# KO
when /\/messages\/name\/(.*)/ # traffic, ...
expr=$1
super(:messages)['messages'].select{|v| v['message'].has_key?('name') && v['message']['name'].match(expr)}
# KO
when /\/messages\/type\/(.*)/ # traffic, ...
expr=$1
super(:messages)['messages'].select{|v| v['message'].has_key?('type') && v['message']['type'].match(expr)}
when /\/lines\/*$/
super(:lines)
when /\/line\/id\/(.+)$/
super :lines, {:lineId => $1}
# KO
when /\/line\/name\/(.+)$/
super(:lines)['lines']['line'].select{|v| v.has_key?('name') && v['name'].match($1)}
# /line/<number>/<name>/<number> - selectionne <number> dans la liste (1=premier)
when /\/line\/(\d+)\/(.*)\/(\d+)$/
self.get("/line/#{$1}/#{$2}")[$3.to_i-1]
# /line/<number>/<name>/next - prochains passages
when /\/line\/(\d+)\/(.*)\/next$/
res=[]
stops=self.xpath("/line/#{$1}/#{$2}")
stops.each do |stop|
res << super(:stops_schedules, { :stopPointId => stop['id'], :cache => false})
end
return res
# /line/<number> - filtre par le n° de ligne - recupère l'enregistrement
when /\/line\/(\d+)$/
super(:lines, { :shortName => $1})['lines']['line']
# /line/<number>/ - filtre par le n° de ligne - liste TOUS les points d'arrets
when /\/line\/(\d+)\/$/
line=self.xpath("/line/#{$1}")
super(:stop_points, { :lineId => line[0]['id']})['physicalStops']['physicalStop']
# /line/<number>/<name> - non sensitive case search.
when /\/line\/(\d+)\/(.*)$/
line=$1
name=expr=$2.downcase
self.get("/line/#{line}/").select{|v| v.has_key?('name') && v['name'].downcase.include?(name) }
# /place/city/<expr> - recherche une ville (city)
when /\/places\/city\/(.*)\/*$/
super(:places, { :term => $1, :displayOnlyCities => 1 })
# /place/public/<expr> - recherche portant sur un lieu public (place)
when /\/places\/public\/(.*)\/*$/
self.get(:places, { :term => $1, :displayOnlyPublicPlaces => 1 })
# /place/road/<expr> - recherche portant sur un lieu public (place)
when /\/places\/road\/(.*)\/*$/
super(:places, { :term => $1, :displayOnlyRoads => 1 })
# /place/stop/<expr> - recherche les arrets pour <expr>
when /\/places\/stop\/(.*)\/*$/
super(:places, { :term => $1, :displayOnlyStopAreas => 1 })
# /place/<expr>/ - recherche portant sur un lieu (place)
when /\/places\/(.*)\/*$/
super(:places, { :term => $1 })
else
return "commande non reconnue"
end
end
end
# la clé ne doit pas être publique
# si vous publiez vos sources, elle pourra être stockée dans $HOME/.config/tisseo.rb
user_cnf=sprintf('%s/.config/tisseo.rb', ENV['HOME'])
if File.exist? user_cnf
require user_cnf
@config=Tisseo::config
else
@config = {
# vous n'avez pas de clé : envoyez un message a contact[arobase]tisseo.fr
# en précisant : votre identité, l'usage que vous ferez de l'API TISSEO
:key => 'xxxxxxxx-yyyy-zzzz-kkkk-vvvvvvvvvvvv',
:lang => :en # only supported : fr, en
}
end
rest = TisseoRest.new @config[:key]
rest.opts[:lang] = :en
tisseo = TisseoRestful.new rest
if ARGV.size>=1
cmd=ARGV[0]
else
puts "usage : ruby tisseo.rb '/restfull/expr'"
end
pp tisseo.get ARGV[0]
@enzofrnt
Copy link

Bonjour,

sauriez-vous comment obtenir une clef API pour Tisséo aujourd'hui ?

Merci !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment