A Spring Boot application that bridges IDFM (Île-de-France Mobilités) real-time transit data to GTFS-Realtime.
This service fetches real-time transit information from the IDFM network and converts it into standardized GTFS-Realtime Protocol Buffer files. It provides REST endpoints to access:
- GTFS-RT Alerts: Service disruptions, delays, and transit alerts
- GTFS-RT Trip Updates: Real-time vehicle positions, estimated arrival/departure times, and schedule adherence
If you want to directly get feeds messages online, you can use my own HTTP links containing the GTFS-RT feeds !
GTFS-RT Trip Updates : http://gtfsidfm.clarifygdps.com/gtfs-rt-trips-idfm
GTFS-RT Alerts : http://gtfsidfm.clarifygdps.com/gtfs-rt-alerts-idfm
Enriched GTFS Static : http://gtfsidfm.clarifygdps.com/gtfs
- 🚆 Real-time Transit Data: Automatic fetching and processing of IDFM transit data
- 📡 Multiple Format Support: GTFS-Realtime (Protocol Buffers) and SIRI-Lite (JSON)
- 🔄 Scheduled Updates: Periodic data synchronization with configurable intervals
- 🐋 Docker Support: Easy deployment with Docker and Docker Compose
- 📊 Trip Matching: Intelligent matching of real-time data with scheduled GTFS trips
- 🗄️ SQLite Database: Local GTFS data storage for fast access
- ⚡ High Performance: Optimized for handling large transit networks
- 🚉 Platform/Track Assignment: Real-time platform codes via
stop_time_properties.assigned_stop_idsourced from SIRI LiteExpectedQuayRef, included directly in the main trip updates feed - 🗺️ Enriched GTFS Static:
stops.txtenriched withplatform_codeand missing quay stops created from IDFM open-data - 🛗 Elevator Pathways:
pathways.txtgenerated with elevator connections (pathway_mode=5) from IDFMetat-des-ascenseursopen-data - ♿ Elevator Outage Alerts: Out-of-service elevators published as
ACCESSIBILITY_ISSUEalerts in the GTFS-RT alerts feed
- Java 21: Modern Java runtime
- Spring Boot 3.5.6: Application framework with scheduling support
- GTFS Realtime Bindings 0.0.8: Protocol Buffer handling
- OneBusAway GTFS 10.2.0: GTFS data processing
- SQLite 3.50.3.0: Local database storage
- Jackson Databind: JSON processing
- OpenCSV 5.12.0: CSV file parsing
- Apache Commons DBCP2 2.13.0: Database connection pooling
- Maven: Build and dependency management
- Docker: Containerization
- JaCoCo 0.8.12: Code coverage reporting
- Java 21 or higher
- Maven 3.6+
- Docker & Docker Compose (for containerized deployment)
- Node.js 22+ (for gtfs-import tool)
- IDFM API Key (required for accessing real-time data)
Before running the application, you need to set up the GTFS static data database:
- Download GTFS data from IDFM or specify
GTFS_URLin your.envfile - Import GTFS into SQLite using the gtfs-import tool (Node.js required):
# Install node-gtfs globally npm install -g gtfs # Import GTFS data gtfs-import --gtfsPath=/path/to/gtfs.zip --sqlitePath=gtfs.db
- Place
gtfs.dbin the project root directory
The application will use this database to match real-time updates with scheduled trips.
-
Create a
.envfile from the exampleYou need to create a
.envfile based on the provided.env.example: -
Run the container
docker run -d \ --name gtfs_app \ --env-file .env \ -p 8507:8507 \ ghcr.io/jouca/idfm_gtfs-rt:latest
The application will be available at
http://localhost:8507
-
Clone the repository
git clone https://github.com/Jouca/IDFM_GTFS-RT.git cd IDFM_GTFS-RT -
Create environment file
cp .env.example .env # Edit .env with your configuration -
Build and run with Docker Compose
docker compose up -d
The application will be available at http://localhost:8507
-
Clone and build
git clone https://github.com/Jouca/IDFM_GTFS-RT.git cd IDFM_GTFS-RT mvn clean package -
Run the application
java -jar target/idfm_gtfs_rt-1.0.6.jar
Configuration is managed through application.properties and environment variables:
# Application name (configurable via SPRING_APPLICATION_NAME env var)
spring.application.name=${SPRING_APPLICATION_NAME:idfm_gtfs_rt}
# Server port (default: 8507, configurable via SERVER_PORT env var)
server.port=${SERVER_PORT:8507}
# Minutes around now (+/-) to include theoretical trips as CANCELED if missing in realtime
gtfsrt.cancellation.window.minutes=120
# Logging Configuration
logging.level.root=INFO
logging.level.org.jouca.idfm_gtfs_rt=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%nCreate a .env file with the following variables:
# Spring Application Configuration
SPRING_APPLICATION_NAME=idfm_gtfs_rt
# Server Configuration
SERVER_PORT=8507
# API Configuration
# Your API key for accessing IDFM services
API_KEY=your_api_key_here
# (OPTIONAL) GTFS Data Source
# URL to download the GTFS static data (ZIP file)
GTFS_URL=https://example.com/path/to/gtfs.zipSee .env.example for a complete template with all available configuration options.
Download GTFS-RT alerts feed (Protocol Buffer format)
Response: Binary .pb file containing two types of alerts:
- Service disruptions: delays, cancellations, and transit alerts from IDFM
- Elevator outages:
ACCESSIBILITY_ISSUEalerts (causeTECHNICAL_PROBLEM, severityWARNING) for each elevator with statusnotavailable, sourced from the IDFMetat-des-ascenseursopen-data. Each alert references the parent station viainformed_entity.stop_id = "IDFM:{zdcid}".
Example:
curl -O http://localhost:8507/gtfs-rt-alerts-idfmDownload GTFS-RT trip updates feed (Protocol Buffer format)
Response: Binary .pb file containing trip updates with stop_time_properties.assigned_stop_id set on each StopTimeUpdate where SIRI Lite provides an ExpectedQuayRef. This field indicates the real-time platform or track assignment without altering the scheduled stop_id.
Use this feed together with the enriched GTFS from /gtfs to display platform/track numbers to passengers.
Example:
curl -O http://localhost:8507/gtfs-rt-trips-idfmRetrieve specific trip entities by their IDs
Parameters:
tripIds(required): Comma-separated list of trip IDs
Example:
curl -X POST "http://localhost:8507/getEntities?tripIds=trip1,trip2,trip3"Response: JSON object mapping trip IDs to their entity data
Download the enriched GTFS static ZIP file
Response: A ZIP file equivalent to the standard IDFM GTFS feed with the following enrichments:
stops.txt
platform_codecolumn populated for existing quay-level stops (e.g.IDFM:471134) using thepubliccodefield from the IDFMarrets-transporteuropen-data dataset- New rows appended for quay stops present in the open-data but missing from the standard GTFS feed, with coordinates and
parent_stationresolved from the IDFMrelationsdataset - Virtual elevator stops (
location_type=2,stop_id=IDFM:elevator:{id}) added for stations where no entrance node already exists
pathways.txt (generated)
- Elevator pathways (
pathway_mode=5,is_bidirectional=1) connecting elevator stops to the nearest platform in the same station, with traversal time estimated from distance at 0.5 m/s (minimum 30 s), sourced from the IDFMetat-des-ascenseursopen-data dataset
This file is intended to be used alongside /gtfs-rt-trips-idfm so consumers can resolve assigned_stop_id values to their platform codes.
Example:
curl -O http://localhost:8507/gtfsDownload the raw SIRI-Lite data as pretty-printed JSON
Response: JSON file containing the last SIRI-Lite response fetched from IDFM, formatted with 4-space indentation. Only available when the application is started with the debug Spring profile.
Download the raw alerts data as pretty-printed JSON
Response: JSON file containing the last alerts response fetched from IDFM, formatted with 4-space indentation. Only available when the application is started with the debug Spring profile.
idfm_gtfs-rt/
├── src/main/java/org/jouca/idfm_gtfs_rt/
│ ├── GTFSRTApplication.java # Main application entry point
│ ├── controller/
│ │ └── GTFSRTController.java # REST API endpoints
│ ├── fetchers/
│ │ ├── AlertFetcher.java # Fetches alert data
│ │ ├── ElevatorEnricher.java # Fetches elevator data; adds pathways.txt and elevator stops
│ │ ├── GTFSEnricher.java # Enriches GTFS stops with platform_code, missing quays, and elevators
│ │ ├── GTFSFetcher.java # Fetches and imports GTFS static data
│ │ └── SiriLiteFetcher.java # Fetches SIRI-Lite data
│ ├── finders/
│ │ └── TripFinder.java # Matches real-time data to trips
│ ├── generator/
│ │ ├── AlertGenerator.java # Generates GTFS-RT alerts (transit + elevator outages)
│ │ ├── ElevatorAlertGenerator.java # Appends ACCESSIBILITY_ISSUE alerts for out-of-service elevators
│ │ └── TripUpdateGenerator.java # Generates GTFS-RT trip updates with platform assignments
│ ├── records/
│ │ └── EstimatedCall.java # Data models
│ └── services/
│ └── ScheduledTasks.java # Background data update tasks
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Docker image definition
└── pom.xml # Maven dependencies
- Data Fetching: The application periodically fetches GTFS static data and real-time updates from IDFM
- GTFS Enrichment: After downloading the GTFS ZIP,
GTFSEnricherproduces an enriched copy (IDFM-gtfs-enriched.zip) by:- Populating
platform_codeinstops.txtfor all quay-level stops using IDFMarrets-transporteuropen-data - Appending new rows for quay stops present in the open-data but absent from the GTFS, with coordinates and
parent_stationfrom IDFMrelationsopen-data - Adding virtual elevator stops (
location_type=2) and generatingpathways.txtwith elevator connections (pathway_mode=5) viaElevatorEnricher, sourced from IDFMetat-des-ascenseursopen-data
- Populating
- Trip Matching: Real-time SIRI-Lite data is matched with scheduled trips using
TripFinder - Format Conversion: Data is converted to GTFS-RT Protocol Buffers
- Platform Assignment:
stop_time_properties.assigned_stop_idis added to eachStopTimeUpdatewhere SIRI Lite provides anExpectedQuayRef, directly ingtfs-rt-trips-idfm.pb - Elevator Alerts: Out-of-service elevators are appended as
ACCESSIBILITY_ISSUEalerts to the GTFS-RT alerts feed byElevatorAlertGenerator - File Generation: Updated feeds are written to
.pband.jsonfiles - API Serving: REST endpoints serve the latest feed data to clients
IDFM arrets-transporteur ──┐
IDFM relations.csv ├──► GTFSEnricher ──► IDFM-gtfs-enriched.zip (platform_code, missing quays)
IDFM etat-des-ascenseurs ──┘ │ + pathways.txt (elevator connections)
│
SIRI Lite (ExpectedQuayRef) ─────────┴──► gtfs-rt-trips-idfm.pb (assigned_stop_id)
IDFM etat-des-ascenseurs ──────────────► gtfs-rt-alerts-idfm.pb (ACCESSIBILITY_ISSUE)
Consumers combine the enriched GTFS with the trip updates feed: the enriched GTFS provides platform_code per quay stop and elevator pathway data, while the trip updates feed provides real-time quay assignments via assigned_stop_id.
The application is containerized for easy deployment:
- Memory Limit: 12GB
- CPU Limit: 8 cores
- Port: 8507
- Network: Isolated bridge network (
gtfs_net) - Restart Policy: unless-stopped (automatically restarts on failure)
# Build and start
docker compose up -d
# Build without cache
docker compose build --no-cache
# View logs
docker compose logs -f
# Stop services
docker compose down
# Stop and remove volumes
docker compose down -v
# Restart services
docker compose restartThe Docker container is configured with the following resource limits:
- Memory: 12GB
- CPUs: 8 cores
- Restart Policy: unless-stopped
Run tests with Maven:
mvn testThe project includes JaCoCo for code coverage analysis. After running tests, view the coverage report:
mvn test
open target/site/jacoco/index.htmlCoverage reports are available in:
- HTML format:
target/site/jacoco/index.html - XML format:
target/site/jacoco/jacoco.xml - CSV format:
target/site/jacoco/jacoco.csv
# Clean and build
mvn clean package
# Skip tests
mvn clean package -DskipTests
# Run locally
mvn spring-boot:runEdit pom.xml and run:
mvn dependency:resolveContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
-
Arno Cellarier for contribution & helping with a better matching algorithm for RATP lines.
-
IDFM (Île-de-France Mobilités) for providing transit data
-
MobilityData for GTFS-Realtime specifications
-
OneBusAway for GTFS processing libraries
-
NodeGTFS for providing a library for decompressing a GTFS file into a SQLite database
- GTFS-Realtime Specification
- SIRI-Lite Documentation
- Spring Boot Documentation
- API for GTFS-RT Trips: Next Departures (Île-de-France Mobilités platform) – Global Query
- API for GTFS-RT Alerts: Traffic Info Messages – Global Query
Application won't start
- Verify Java 21 is installed:
java -version - Check if port 8507 is available:
lsof -i :8507 - Ensure
.envfile is properly configured - Verify API_KEY is set in
.envfile
Docker container exits immediately
- Check container logs:
docker compose logs -f - Verify
.envfile exists and is properly formatted - Ensure sufficient system resources (12GB RAM, 8 CPU cores)
No data in feeds
- Verify API_KEY is valid
- Check logs for API connection errors
- Ensure GTFS database (
gtfs.db) is present and not corrupted - Verify GTFS_URL (if set) points to a valid GTFS ZIP file
High memory usage
- This is expected for large transit networks
- Adjust
mem_limitindocker-compose.ymlif needed - Monitor with:
docker stats gtfs_app
To enable debug logging, update application.properties:
logging.level.org.jouca.idfm_gtfs_rt=DEBUGOr set in .env:
LOGGING_LEVEL_ORG_JOUCA_IDFM_GTFS_RT=DEBUGIf you encounter any issues, please file a bug report on the GitHub Issues page.
Note: This is an unofficial project and is not affiliated with IDFM or Île-de-France Mobilités.
