A public transportation tracking and analytics platform for Athens (and Thessaloniki, WIP), Greece. This Rails application synchronizes real-time and scheduled bus data from OASA (Athens Urban Transport Organization) and THESS telematics APIs, providing route statistics, vehicle tracking, and schedule comparisons.
Live at: athensbus.info
- Real-time Bus Tracking: Fetch and display live vehicle locations for bus routes
- Schedule Synchronization: Sync and store both normal and daily bus schedules
- Route Analytics: Generate daily reports with statistics on route coverage and performance
- Vehicle Count Tracking: Monitor and calculate daily vehicle counts per route
- Stop Management: Automatically sync and geocode bus stop information
- Multi-City Support: Support for both Athens and Thessaloniki public transit systems
- Reporting Dashboard: View estimated coverage, schedule comparisons, and vehicle statistics
- Background Job Processing: Automated data synchronization via Solid Queue
- Rails: 8.0.1
- Ruby: 3.3.5
- Database: PostgreSQL (production), SQLite3 (development/test)
- Job Queue: Solid Queue with Mission Control interface
- Cache: Solid Cache
- Frontend: Hotwire (Turbo + Stimulus), Importmap
- Charts: Chartkick
- Deployment: Kamal (Docker-based deployment)
- Error Tracking: Honeybadger
- Geocoding: Geocoder gem
- Ruby 3.3.5 or higher
- PostgreSQL (production)
- SQLite3 (development/test)
- Docker (for deployment)
git clone <repository-url>
cd oasabundle install# Create and migrate the database
bin/rails db:create
bin/rails db:migrate
# Seed initial data (if applicable)
bin/rails db:seed
# and in a Rails console
r = RestClient.get("#{TELEMATICS_BASE_URL}/api/?act=webGetLines")
lines = JSON.parse(r.body)
lines.each do |line|
Populators::Line.populate(line)
endCreate a .env file or set the following environment variables:
# City configuration
CITY_NAME=athens # or 'thessaloniki'
TELEMATICS_BASE_URL=http://telematics.oasa.gr # Athens
# TELEMATICS_BASE_URL=http://oasth.gr/el # Thessaloniki
# Database (production)
DB_HOST=localhost
DB_PORT=5432
POSTGRES_DB=oasa_production
POSTGRES_USER=oasa
POSTGRES_PASSWORD=your_password
# Error tracking
HONEYBADGER_API_KEY=your_api_key
# Job processing
JOB_CONCURRENCY=6
# Rails
RAILS_MASTER_KEY=your_master_keybin/rails serverThe application will be available at http://localhost:3000
Start the Solid Queue worker:
bin/jobsOr run jobs within Puma (development):
SOLID_QUEUE_IN_PUMA=true bin/rails serverAccess Mission Control at: http://localhost:3000/jobs
# Run all tests
bin/rails test
# Run specific test files
bin/rails test test/models/route_test.rb
bin/rails test test/services/schedules/athens/normal_schedule_syncer_test.rb
# Run with coverage
COVERAGE=true bin/rails testThe application runs several recurring jobs (configured in config/recurring.yml):
- Sync Stops (every 5 minutes): Fetches and updates bus stop data
- Generate Daily Reports (daily at 00:00): Creates route performance reports
- Delete Old Data (daily at 00:00): Cleans up historical data
- Sync Schedules (daily at 00:00, 08:00, 23:00): Updates bus schedules
- Calculate Daily Vehicle Count (daily at 00:00): Computes vehicle statistics
Schedules::Athens::NormalScheduleSyncer: Syncs regular schedules from OASA APISchedules::Athens::DailyScheduleSyncer: Syncs daily variationsSchedules::Thessaloniki::NormalScheduleSyncer: Syncs Thessaloniki schedules
StopSyncer: Updates bus stop information and geocodingTripExtractor: Extracts trip data from arrival informationTripsCalculator: Calculates trip statisticsDailyVehicleCountCalculator: Computes daily vehicle countsRouteDailyReports::Creator: Generates comprehensive route reports
Populators::Line: Seeds line dataPopulators::Route: Seeds route data
GET /- Lines index pageGET /lines- List all linesGET /routes/:code/stats- Route statistics pageGET /reports- Reports dashboard/reports/estimated_coverage- Coverage reports/reports/daily_vs_normal- Schedule comparison/reports/vehicles- Vehicle reports/reports/vehicle_count- Vehicle count statistics/reports/stops- Stop reports
GET /about- About pageGET /up- Health check endpoint
This application uses Kamal for Docker-based deployment.
- Docker installed on your deployment server
- Docker Hub account (or other registry)
- Server with SSH access
# First time setup
bin/kamal setup
# Deploy updates
bin/kamal deploy
# Useful aliases (defined in config/deploy.yml)
bin/kamal console # Rails console
bin/kamal shell # Server shell
bin/kamal logs # Tail logs
bin/kamal dbc # Database console- Athens:
config/deploy.yml - Thessaloniki:
config/deploy-thess.yml
- Rubocop: Ruby style linting (
bundle exec rubocop) - Brakeman: Security vulnerability scanner (
bundle exec brakeman) - Bullet: N+1 query detection (automatically enabled in development)
Install Lefthook for automated checks:
bundle exec lefthook install- Use
debuggem: Adddebuggerin your code - Web Console: Available in development on error pages
- Mission Control: Monitor jobs at
/jobs
Key models:
- Line: Bus line (e.g., "X95", "040")
- Route: Specific route direction for a line
- Stop: Bus stop location
- RoutesStop: Join table linking routes to stops in order
- Schedule: Bus schedules (normal and daily)
- Arrival: Real-time arrival predictions
- Vehicle: Vehicle tracking data
- RouteDailyReport: Daily analytics per route
- DailyVehicleCount: Daily vehicle count statistics
- Create a feature branch
- Make your changes
- Run tests:
bin/rails test - Run linters:
bundle exec rubocop - Commit your changes
- Push and create a pull request
MIT License - see LICENSE file for details
For issues and questions, please open an issue on GitHub.