RESTful Sensor Template

I am trying to extract specific attributes from a JSON api to pull real-time train arrivals for the DC metro system (WMATA). So far I have been able to pull the first train listed (value_template: '{{ value_json.Trains[0].Min }}), but I am struggling with specifying I want to the first train in a certain direction (specified by the ‘Destination’). Can this be done via a template or is the JSON too complex?

My current configuration is:

[code]

Which produces:

[
    {
      "Car": "6",
      "Destination": "Shady Gr",
      "DestinationCode": "A15",
      "DestinationName": "Shady Grove",
      "Group": "2",
      "Line": "RD",
      "LocationCode": "A01",
      "LocationName": "Metro Center",
      "Min": "BRD"
    },
    {
      "Car": "8",
      "Destination": "SilvrSpg",
      "DestinationCode": "B08",
      "DestinationName": "Silver Spring",
      "Group": "1",
      "Line": "RD",
      "LocationCode": "A01",
      "LocationName": "Metro Center",
      "Min": "ARR"
    },
    {
      "Car": "6",
      "Destination": "Shady Gr",
      "DestinationCode": "A15",
      "DestinationName": "Shady Grove",
      "Group": "2",
      "Line": "RD",
      "LocationCode": "A01",
      "LocationName": "Metro Center",
      "Min": "5"
    },
    {
      "Car": "6",
      "Destination": "Glenmont",
      "DestinationCode": "B11",
      "DestinationName": "Glenmont",
      "Group": "1",
      "Line": "RD",
      "LocationCode": "A01",
      "LocationName": "Metro Center",
      "Min": "7"
    },
    {
      "Car": "8",
      "Destination": "Shady Gr",
      "DestinationCode": "A15",
      "DestinationName": "Shady Grove",
      "Group": "2",
      "Line": "RD",
      "LocationCode": "A01",
      "LocationName": "Metro Center",
      "Min": "9"
    },
    {
      "Car": "8",
      "Destination": "SilvrSpg",
      "DestinationCode": "B08",
      "DestinationName": "Silver Spring",
      "Group": "1",
      "Line": "RD",
      "LocationCode": "A01",
      "LocationName": "Metro Center",
      "Min": "13"
    }
  ]

Adding [2] for example to value_template: ‘{{ value_json.Trains[2].Min }}’ returns ‘5’. How can I use the value_template to only show, say the first result, with a ‘DestinationCode’ of B08 or B11?

Bonus question: is it also possible to ignore results when the ‘Min’ attribute returns ARR or BRD? Since I don’t live on top of a station, its too late to catch these trains.

Any luck on this?

The following is a rudimentary way. In my case I will take the green or yellow to get to DC. You could switch to test DestinationCode for a specific end.

This is only using 2 if statements nested. It will check the first two, if neither match it gives you the third train. Looking into looping through all the trains given back by the API. It’s a start.

  - platform: rest
    name: WMATA Pentegon City
    resource: https://api.wmata.com/StationPrediction.svc/json/GetPrediction/C08
    method: GET
    headers:
      api_key: !secret wmata_secret
    value_template: >
      {% if (value_json.Trains[0].Group == 1) and (value_json.Trains[0].Min != or('BRD','ARR','---','')) %}
        {{ value_json.Trains[0].DestinationName }} leaving in {{ value_json.Trains[0].Min }}
      {% else %}
        {% if (value_json.Trains[1].Group == 1) and (value_json.Trains[1].Min != or('BRD','ARR','---','')) %}
          {{ value_json.Trains[1].DestinationName }} leaving in {{ value_json.Trains[1].Min }}
        {% else %}
          {{ value_json.Trains[2].DestinationName }} leaving in {{ value_json.Trains[2].Min }}
        {% endif %}
      {% endif %}

Update: This is much better.

This template will give you a list of all the upcoming matches

{% set ns = namespace(found=false) %}
{% for i in value_json.Trains %}
    {%- if (i.Group|int == 1) and i.Min not in ('BRD','ARR','---','') %}
      {% set ns.found = true %}
      {{ i.DestinationName }} {{ i.Line }} in {{ i.Min }}
    {% endif -%}
{% endfor %}
{% if not ns.found %} No Trains {% endif %}

This template will give the minutes to arrival of the next matching train. You could add in more |selectattr(‘Group’, ‘eq’, ‘1’) to narrow down the destination or color

{{ (value_json.Trains|selectattr('Group', 'eq', '1')
|rejectattr('Min', 'eq', 'BRD')|rejectattr('Min', 'eq', 'ARR')
|rejectattr('Min', 'eq', '---')|rejectattr('Min', 'eq', '')|first).Min }}

This template will give the first matching train in a short sentence. You could add in more |selectattr(‘Group’, ‘eq’, ‘1’) to narrow down the destination or color

{% set value_json = (value_json.Trains|selectattr('Group', 'eq', '1')
|rejectattr('Min', 'eq', 'BRD')|rejectattr('Min', 'eq', 'ARR')
|rejectattr('Min', 'eq', '---')|rejectattr('Min', 'eq', '')|first) %}
{% if value_json|length %}
    {{ value_json.DestinationName }} {{ value_json.Line }} in {{ value_json.Min }}
{% else %}
    No Trains
{% endif %}