Skip to content
Home Assistant 5 min read

Your Tallinn Commute in Home Assistant

Your Tallinn Commute in Home Assistant

Living in Tallinn, the city's rhythm is often set by the arrival of the next bus or tram. We’ve all been there, quickly checking transport.tallinn.ee or peatus.ee, or a mobile app before dashing out the door. It’s functional, but it’s reactive. The core philosophy of a truly smart home is to move from being reactive to proactive. What if that information was just there, presented on a dashboard next to the weather and my calendar, giving me a passive awareness of my transport options?

I decided to build my own custom integration to solve this for myself. I'm excited to share the Tallinn Public Transport integration for Home Assistant, a project born from a daily need. It leverages the publicly available data source to bring a vital piece of our city’s infrastructure into our local smart home hubs.

Getting Started: Installation and Setup

Like many of the best community projects, the easiest way to get this running is through the Home Assistant Community Store (HACS).

  1. In HACS, add the custom repository: Here or https://github.com/zaifkhan/tallinn_transport
  2. Search for "Tallinn Public Transport" and install the integration.
  3. Restart Home Assistant to apply the changes.

Once restarted, the configuration is handled neatly through the UI. Navigate to Settings > Devices & Services and click "+ Add Integration". Search for "Tallinn Public Transport" to begin. The setup will ask for three things: a name for your stop, the stop number (ID), and the update frequency.

Finding Your Stop ID

This is the most crucial step. The stop ID isn't the number you see on the physical sign, but rather a unique identifier from the peatus.ee system.

  1. Visit the peatus.ee website.
  2. Search for and select your desired bus or tram stop.
  3. Look at the URL in your browser's address bar. It will look something like this: https://web.peatus.ee/pysakit/estonia%3A1076
  4. The stop number is the set of digits after estonia%3A. In this example, the ID is 1076.

Enter this number into the configuration flow, and you're all set.

Putting It on Display: Lovelace Configuration

Once configured, the integration creates a set of sensors for your stop. The most useful one is sensor.tallinn_transport_[your_stop_name]_next, that shows the very next departure. For more details, you get up to 10 additional sensors (..._departure_1, ..._departure_2, etc.).

You can list these in an entities card for a simple display. But for a truly clean and data-rich view, the template-entity-row custom card is the way to go. It lets you combine the state (departure time) with the key attributes (route number and destination) into a single, elegant line.

Simple card with the selected tram information

Here’s a configuration for my local "Tallinn-Väike" tram stop that presents the next 5 departures clearly:

type: vertical-stack
cards:
  - type: markdown
    content: >
      ## Tallinn-Väike Stop
  - type: entities
    state_color: false
    entities:
      - type: custom:template-entity-row
        icon: mdi:tram
        name: >
          {{ states('sensor.tallinn_transport_tallinn_vaike_departure_1') }} ⠀⠀⠀⠀ Tram: {{
          state_attr('sensor.tallinn_transport_tallinn_vaike_departure_1', 'route_number') }} ⠀⠀⠀⠀ {{
          state_attr('sensor.tallinn_transport_tallinn_vaike_departure_1', 'headsign') }}
      - type: custom:template-entity-row
        icon: mdi:tram
        name: >
          {{ states('sensor.tallinn_transport_tallinn_vaike_departure_2') }} ⠀⠀⠀⠀ Tram: {{
          state_attr('sensor.tallinn_transport_tallinn_vaike_departure_2', 'route_number') }} ⠀⠀⠀⠀ {{
          state_attr('sensor.tallinn_transport_tallinn_vaike_departure_2', 'headsign') }}
      - type: custom:template-entity-row
        icon: mdi:tram
        name: >
          {{ states('sensor.tallinn_transport_tallinn_vaike_departure_3') }} ⠀⠀⠀⠀ Tram: {{
          state_attr('sensor.tallinn_transport_tallinn_vaike_departure_3', 'route_number') }} ⠀⠀⠀⠀ {{
          state_attr('sensor.tallinn_transport_tallinn_vaike_departure_3', 'headsign') }}
      - type: custom:template-entity-row
      # ...and so on for more departures
    show_header_toggle: false

Example configuration for the simple card

A more comprehensive dashboard with various routes, and live data in an iframe

Making It Proactive: A Time to Leave Automation

Example 1: General Time to Leave Automation

Displaying data is useful, but the real power of the Home Assistant is in automation. Here’s a simple automation that can notify your phone when it's time to leave, but only when you’re home.

alias: Notify When Tram is Approaching
trigger:
  - platform: template
    value_template: >-
  {% set time_diff = states('sensor.tallinn_transport_tallinn_vaike_next') | as_timestamp - now() | as_timestamp %}
  {{ time_diff <= 600 and time_diff > 0 }}
condition:
  - condition: state
    entity_id: person.your_person_entity
    state: 'home'
action:
  - service: notify.mobile_app_your_phone
    data:
      title: 'Time to Go!'
      message: >-
        The next tram ({{
        state_attr('sensor.tallinn_transport_tallinn_vaike_next', 'route_number')
        }}) to {{ state_attr('sensor.tallinn_transport_tallinn_vaike_next', 'headsign')
        }} departs at {{
        states('sensor.tallinn_transport_tallinn_vaike_next') }}.
mode: single

Example YAML for time to leave automation

This automation triggers when the next departure is less than 10 minutes (600 seconds) away, giving me a gentle nudge to put on my shoes and head out the door.

Example 2: Advanced Work Commute Automation

The general automation is great, but what about a specific routine like commuting to work? Let's refine it to only notify us for a tram around a specific departure time, for example, to leave before 9 AM on a weekday.

This more intelligent version will only trigger on weekdays (Monday to Friday) and only if the next departing tram is within a specific "work window" (e.g., between 8:50 AM and 9:05 AM). This prevents unnecessary notifications for trams that are too early or too late, helping you catch the perfect one even when there's a schedule change.

alias: Notify When Work Tram is Approaching
trigger:
  - platform: template
    value_template: >-
      {# Define our target departure window for the work commute #}
      {% set target_start = today_at("08:50") | as_timestamp %}
      {% set target_end = today_at("09:05") | as_timestamp %}
      
      {# Get the timestamp of the next tram departure #}
      {% set next_departure = states('sensor.tallinn_transport_tallinn_vaike_next') | as_timestamp(0) %}
      
      {# Check if the next departure is within our target window AND is less than 10 minutes away #}
      {{ target_start < next_departure < target_end and 
         next_departure - now() | as_timestamp < 600 }}
condition:
  - condition: and
    conditions:
      # Only trigger if you are at home
      - condition: state
        entity_id: person.your_person_entity
        state: 'home'
      # Only trigger on weekdays
      - condition: time
        weekday:
          - mon
          - tue
          - wed
          - thu
          - fri
action:
  - service: notify.mobile_app_your_phone
    data:
      title: 'Time for Work!'
      message: >-
        The next tram ({{
        state_attr('sensor.tallinn_transport_tallinn_vaike_next', 'route_number')
        }}) to {{ state_attr('sensor.tallinn_transport_tallinn_vaike_next', 'headsign')
        }} departs at {{
        states('sensor.tallinn_transport_tallinn_vaike_next') }}.
mode: single

Example YAML for an advance commute notification automation

By adding a time-based condition and a more specific template trigger, the automation becomes a helpful assistant for a daily routine, only alerting you when the information is most relevant.

Final Thoughts

This integration is an example of what makes the Home Assistant community so powerful. It transforms a piece of public, open data from something you have to actively seek out into a passive, integrated part of your home's awareness.


Note: This integration might work for other Estonian cities and uses publicly available data, which might not be 100% accurate for your specific location and is not affiliated with any official transport schedule or data provider.