REST sensor: Ignoring some values when json parsing

Hi

I’m struggling with parsing bus times from a json response I get from a bus company website.I want to put the time for when the next bus is leaving in a sensor. This works well for busstops that are only served by one route. I use this as a sensor:

platform: rest
resource: https://skyss.giantleap.no/public/departures?Hours=12&StopIdentifiers=12012101
name: skyss50E_1
value_template: '{{ value_json["PassingTimes"][0]["DisplayTime"] }}'

The json I get from a busstop with multiple routes:

{"PassingTimes":[{"RouteDirectionIdentifier":"000004_0_Direction2","RoutePublicIdentifier":"4","StopIdentifier":"12015177","TripDestination":"Flaktveit","TripDestinationDescription":"","Status":"Late","AimedTime":"2018-10-12T06:59:00.000Z","DisplayTime":"2 min"},{"RouteDirectionIdentifier":"000050_E0_Direction1","RoutePublicIdentifier":"50E","StopIdentifier":"12012101","TripDestination":"Bergen busstasjon","TripDestinationDescription":"","Status":"Early","AimedTime":"2018-10-12T07:03:00.000Z","DisplayTime":"3 min"},{"RouteDirectionIdentifier":"000024_0_Direction1","RoutePublicIdentifier":"24","StopIdentifier":"12012101","TripDestination":"Oasen terminal","TripDestinationDescription":"","Status":"Late","AimedTime":"2018-10-12T07:02:00.000Z","DisplayTime":"4 min"},{"RouteDirectionIdentifier":"000004_0_Direction2","RoutePublicIdentifier":"4","StopIdentifier":"12015177","TripDestination":"Flaktveit","TripDestinationDescription":"","Status":"Late","AimedTime":"2018-10-12T07:09:00.000Z","DisplayTime":"11 min"},{"RouteDirectionIdentifier":"000050_E0_Direction1","RoutePublicIdentifier":"50E","StopIdentifier":"12012101","TripDestination":"Bergen busstasjon","TripDestinationDescription":"","Status":"Early","AimedTime":"2018-10-12T07:18:00.000Z","DisplayTime":"09:17"}}}

The sensor then gives me the time for the next bus, independent of the bus route. What if I only want the times for bus 50E? I don’t know how to tell the sensor to only take the values where the RoutePublicIdentifier is 50E.

any tips?
Thank you

I think the easiest way to do this might be to use a Command Line Sensor that uses curl and jq. jq is a utility that provides advanced features for parsing JSON. E.g.:

platform: command_line
command: curl ... | jq '.PassingTimes|map(select(.RoutePublicIdentifier == "50E"))|.[0]'

Will return the first element of the PassingTimes array whose RoutePublicIdentifier element is “50E”.

I put the JSON output you provided above (with the }}} at the end changed to }]}, since it was originally incorrect) into a file and passed it through the above jq command and got “3 min”.

2 Likes

Thank you so much! I learn something new every day :slight_smile:

I managed to get the right times before you answered with this:

    resource: https://skyss.giantleap.no/public/departures?Hours=12&StopIdentifiers=12012101
    name: skyss50E_1
    value_template: >
      {% if ('{{ value_json["PassingTimes"][0]["RoutePublicIdentifier"] }}', '50E') %}
      {{ value_json["PassingTimes"][0]["DisplayTime"] }}
      {% elif ('{{ value_json["PassingTimes"][1]["RoutePublicIdentifier"] }}', '50E') %}
      {{ value_json["PassingTimes"][1]["DisplayTime"] }}
      {% elif ('{{ value_json["PassingTimes"][2]["RoutePublicIdentifier"] }}', '50E') %}
      {{ value_json["PassingTimes"][2]["DisplayTime"] }}
      {% elif ('{{ value_json["PassingTimes"][3]["RoutePublicIdentifier"] }}', '50E') %}
      {{ value_json["PassingTimes"][3]["DisplayTime"] }}
      {% elif ('{{ value_json["PassingTimes"][4]["RoutePublicIdentifier"] }}', '50E') %}
      {{ value_json["PassingTimes"][4]["DisplayTime"] }}
      {% else %}
      No bus
      {% endif %}

Your solution is way better! Thank you!

I don’t think what you came up with works the way you think it does. The first if should always be true, because you’re testing a tuple, which when evaluated as a boolean always evaluates to true (unless it’s empty, which it isn’t, because in your case it’s a sequence of two strings.) So your template should always return the value of element 0.

What I think you were trying to do is this:

    value_template: >
      {% if value_json["PassingTimes"][0]["RoutePublicIdentifier"] == '50E' %}
      {{ value_json["PassingTimes"][0]["DisplayTime"] }}
      {% elif value_json["PassingTimes"][1]["RoutePublicIdentifier"] == '50E' %}
      {{ value_json["PassingTimes"][1]["DisplayTime"] }}
      {% elif value_json["PassingTimes"][2]["RoutePublicIdentifier"] == '50E' %}
      {{ value_json["PassingTimes"][2]["DisplayTime"] }}
      {% elif value_json["PassingTimes"][3]["RoutePublicIdentifier"] == '50E' %}
      {{ value_json["PassingTimes"][3]["DisplayTime"] }}
      {% elif value_json["PassingTimes"][4]["RoutePublicIdentifier"] == '50E' %}
      {{ value_json["PassingTimes"][4]["DisplayTime"] }}
      {% else %}
      No bus
      {% endif %}
1 Like

Thanks!
Yes, you are right. I still always get the first bus with my code. When I checked the first bus was a 50E and therefore I thought it worked.

As you can see, I have no experience with this stuff. Thanks for helping me!

hello, i see you are working with the JQ command

can you help me with my first question here.? i think i need the same, just dont know how i need to put the JQ in my command line

command: (echo ‘{“cmd”:“listactions”}’; sleep 1) | nc XXXX 8000 | jq ‘.id .value1’

something like that i need? to get .id and .value1 from the data array