Skip to content

5. Visualizing the data

Arjan edited this page Jan 20, 2025 · 30 revisions

Static data and relatime combined

Using 'multiple entity row' card with pop-up (see further below)

image

type: entities
entities:
  - entity: sensor.653_mouans_sophia
    type: custom:multiple-entity-row
    state_header: RealTime
    attribute: next_departure_realtime
    name: Mouans > Sophia 653
    format: time
    secondary_info: last-updated
    entities:
      - entity: sensor.653_mouans_sophia
        attribute: day
        name: Day
        format: time
      - entity: sensor.653_mouans_sophia
        name: 653
        format: time
    tap_action:
      action: fire-dom-event
      browser_mod:
        service: browser_mod.popup
        data:
          content:
            type: custom:button-card
            entity: sensor.653_mouans_sophia
            show_icon: false
            show_state: true
            show_name: false
            tap_action: none
            styles:
              grid:
                - grid-template-areas: "\"next\" \"s\""
              custom_fields:
                next:
                  - font-size: 20px
                  - font-weight: bold
            custom_fields:
              next: |
                [[[ return 'Next departures :' ]]]
            state_display: |
              [[[ 
               return entity.attributes.next_departures.map((entry) => {
                    return '<br>' + [ helpers.formatShortDateTimeWithYear(entry) ] ;
                      }  ).join("").toString();
              ]]]
  - entity: sensor.653_mouans_antibes
    type: custom:multiple-entity-row
    state_header: RealTime
    attribute: next_departure_realtime
    name: Mouans > Antibes 653
    format: time
    secondary_info: last-updated
    entities:
      - entity: sensor.653_mouans_antibes
        attribute: day
        name: Day
        format: time
      - entity: sensor.653_mouans_antibes
        name: 653
        format: time
    tap_action:
      action: fire-dom-event
      browser_mod:
        service: browser_mod.popup
        data:
          content:
            type: custom:button-card
            entity: sensor.653_mouans_antibes
            show_icon: false
            show_state: true
            show_name: false
            tap_action: none
            styles:
              grid:
                - grid-template-areas: "\"next\" \"s\""
              custom_fields:
                next:
                  - font-size: 20px
                  - font-weight: bold
            custom_fields:
              next: |
                [[[ return 'Next departures :' ]]]
            state_display: |
              [[[ 
               return entity.attributes.next_departures.map((entry) => {
                    return '<br>' + [ helpers.formatShortDateTimeWithYear(entry) ] ;
                      }  ).join("").toString();
              ]]]
card_mod:
  style:
    .: |
      ha-card {
        border-width: 0px !important;
        background: none;
      }  

Vehicle positions

When vehcile positions have been added to the configuration, a geojson file is created in your www/gtfs2 folder You can create entities with position, using the geojson integration, refering to that file

important:

image

Example geojson entity:

image Note: to make the entity unique, the name of the entity is a combination of the route 'B', the direction '(0)' and a crc32 of the trip_id (last 3 digits only)

Then you can configure a Map card to show the positions of active vehicles along that route

image

Note: geojson currently only updates each 5 minutes and can be refreshed by a service call on geo_json

Additional improvements can be achieved by customizing the entities.

  1. use customize_glob to use a different entity_picture, in this case a svg of a bus image

Note: svg are not supplied with this integration

  1. Tweak the card to make full use of the SVG, i.e. remove the circle, the background image
type: custom:auto-entities
filter:
  include:
    - entity_id: geo_location.b_0*
  exclude:
    - state: unavailable
show_empty: true
card:
  type: map
  hours_to_show: 2
  auto_fit: true
  card_mod:
    style:
      ha-map:
        $:
          .leaflet-marker-icon:
            ha-entity-marker $: |
              .marker {
                vertical-align: right !important;

                width: 25px !important;
                height: 25px !important;
                border: 0px solid var(--ha-marker-color,var(--primary-color)) !important;
                background-color: var(--ha-marker-color,none) !important;
               }
               .div:hover {
                --webkit-transform: scale(0.1);
                --ms-transform: scale(0.1);
                transform: scale(0.1);
                }

Local stops and departures

image

image

type: custom:auto-entities
filter:
  include:
    - name: '*_local_stop'
  exclude:
    - state: unavailable
card:
  type: custom:flex-table-card
  clickable: true
  max_rows: 30
  title: Local Stop dep.
  strict: true
  sort_by:
    - next_departures_lines
  columns:
    - hidden: true
      data: next_departures_lines
      modify: x.departure
    - name: Route
      data: next_departures_lines
      modify: '''<ha-icon icon='' + x.icon + ''></ha-icon>'' + x.route'
    - name: Time
      data: next_departures_lines
      modify: x.departure
    - name: Stop
      data: next_departures_lines
      modify: x.stop_name
    - name: Headsign
      data: next_departures_lines
      modify: x.headsign
  css:
    table+: 'padding: 0px'
  card_mod:
    style: |
      ha-card {
        overflow: auto;
        max-height: 500px;
      }

Local stops and departures: filtering certain routes

Note: I cannot get this to work with flex-table-card

image

type: vertical-stack
cards:
  - type: entities
    entities:
      - entity: input_text.local_stops_filter
  - type: markdown
    content: >-
      <table>  {% set next =
      state_attr('sensor.01254_0608400_local_stop_person_abcd','next_departures_lines')%}
      {% for i in range(0, next | count, 1) %} {%- if
      state_attr('sensor.01254_0608400_local_stop_person_abcd','next_departures_lines')[i].route 
        == states("input_text.local_stops_filter") -%}
      <tr> <td>{{
      state_attr('sensor.01254_0608400_local_stop_person_abcd','next_departures_lines')[i].route
      }}</td> <td>{{
      state_attr('sensor.01254_0608400_local_stop_person_abcd','next_departures_lines')[i].departure
      }}</td> <td>{{
      state_attr('sensor.01254_0608400_local_stop_person_abcd','next_departures_lines')[i].stop_name
      }}</td> <td>{{
      state_attr('sensor.01254_0608400_local_stop_person_abcd','next_departures_lines')[i].headsign
      }}</td> {% endif %} {% endfor %}
    card_mod:
      style:
        .: |
          ha-card ha-markdown {
                    padding:0px
                    border-top: 1px groove var(--divider-color);
                    overflow-y: scroll;
                    height: 300px;
                  }
          ha-card ha-markdown.no-header {
            padding:0px
          }
        $: |
          h1.card-header {
            background-color:rgb(100, 100, 100);
              padding: 0px 0px 0px 12px !important;
              color: white !important;
              font-weight: normal;
              font-size: 1.5em !important;
              border-top-left-radius: 5px; 
              border-top-right-radius: 5px; 
              height: 100%;
          }        
        ha-markdown $: |
          h1 {
              font-weight: normal;
              font-size: 24px;
          }
          table{
            border-collapse: collapse;
            font-size: 0.9em;
            font-family: Roboto;
            width: 100%;
            outline: 0px solid #393c3d;
            margin-top: 10px;
          }
          td {
              padding: 5px 5px 5px 5px;
              text-align: left;
              border-bottom: 0px solid #1c2020;
          }
          tr:nth-of-type(even) {
              background-color: rgb(54, 54, 54, 0.3);
          }

Local stops: travelling solution

I tied the local-stop sensor to my 'person.abc' entity (contains the lat/lon of my phone). When I move around I click two buttons to see what is near me:

  • Location update (just in case it is not fast in updating my person/position, e.g. with my iPhone it is slow)
  • Local stops update: this updates every entity with local stops tied to my name, I have this setup for France, Switzerland and Netherlands. The map nicely follows me around and adds the stops

Note: one can of course also automate this but as I am not that mobile, nor do I need it all day long, the button-update suffices for me

image

Route: show entity of a route with pop-up containing next departures

Goal is to use entities card and be able to click on a single entry, showing the next known departures.

Important: Requires install of browser-mod (HACS)

image

Change YOURSENSOR to whatever your entity is called


type: entities
entities:
  - entity: YOURSENSOR
    format: datetime
    tap_action:
      action: fire-dom-event
      browser_mod:
        service: browser_mod.popup
        data:
          content:
            type: custom:button-card
            entity: YOURSENSOR
            show_icon: false
            show_state: true
            show_name: false
            tap_action: none
            styles:
              grid:
                - grid-template-areas: "\"next\" \"s\""
              custom_fields:
                next:
                  - font-size: 20px
                  - font-weight: bold
            custom_fields:
              next: |
                [[[ return 'Next departures :' ]]]
            state_display: |
              [[[ 

               return entity.attributes.next_departures.map((entry) => {
                        return '<br>' + [ helpers.formatShortDateTimeWithYear(entry) ];
                      }  ).join("").toString();


              ]]]
Clone this wiki locally