Trouble parsing some JSON

Hi,

I am new to HASS and currently trying to parse some JSON with the RESTful sensor to no avail.

  - platform: rest
    resource: http://environment.data.gov.uk/flood-monitoring/id/stations/1029TH
    name: River Level
    value_template: '{{ value_json.items.measures.latestReading.value}}'

Using jsonpath.com I can match that JSON path succesfully

[
  0.072
]

Yet I get an error in HASS and an “Unknown” value shown in the sensor

2017-05-17 22:20:25 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'builtin_function_or_method object' has no attribute 'measures' (value: { <snip>

I am sure it is a mix up with either the value returned or the JSON path. Can anyone spot what I am doing wrong?

it looks like the data returns a list of measures. In order to get a single value I had to use the following.

items.measures.0.latestReading.value

The 0 is to say give me the first reading from the list, now whether that’s the correct one or not, I don’t know.

Thanks for the reply. I tried that suggestion and got a similar error

2017-05-18 09:09:10 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'builtin_function_or_method object' has no attribute 'measures' (value: { 
  "@context" : "http://environment.data.gov.uk/flood-monitoring/meta/context.jsonld" ,

Did it work OK for you?

What @turboc said is correct, it’s a list of readings, the syntax mentioned is not correct though.

I checked the data and it seems it’s an array of 2 items:
object at index 0: Downstream Stage
object at index 1: Stage

Depending on which value you want to get, you should use the following syntax to get it:

{{ value_json.items.measures[0].latestReading.value}} for Downstream stage
{{ value_json.items.measures[1].latestReading.value}} for Stage

Would be nice to turn this into a flood sensor component :slight_smile:

Thats the plan! Sadly the Environment Agency doesn’t update the data too often. I think new data comes every 12 hours.

Indeed…

Water levels and flows are regularly monitored, usually every 15 minutes. However, data is transferred back to the Environment Agency at various frequencies, usually depending on the site and level of flood risk. Transfer of data is typically once or twice per day, but usually increases during times of heightened flood risk.

I use requests to test parsing of JSON, this may help you out…

On the Flood topic - They don’t cover all areas - “We don’t give flood warnings for this address”

Perhaps combining water level data with rainfall prediction (e.g. from dark sky) you could create a sensor to predict likelihood of severe events…?

did tmatheussen’s reply resolve this? If not, can you post the code you are using please.

It did not, however I notice the JSON is different for some stations than others.

Here’s the particular one I am playing with right now http://environment.data.gov.uk/flood-monitoring/id/stations/700408

It doesn’t have an array for any values, so I assume value_json.items.measures.latestReading.value should work.

Your findings are correct, the fact that the response if different for some stations, would make it harder to create a sensor. Even harder if the response would change depending on the data (let’s hope that’s not the case :stuck_out_tongue: )

as far as I can see, the code you posted should indeed work for that station

I have no idea. I’ve been playing with this for a couple of hours now and I’m getting the same results as you. Templates are why I started using appdaemon. It may take a dozen lines of code, but at least I don’t have a headache at the end of the day.

Sorry about the head ache!

I’ve given up with this. I think I am going to write a bit of middleware that spits out single value for the template to read.
Or read about about appdaemon. (Still learning how HASS works)

Appdaemon is an addon to HA that allows you to write python apps that let you write automations in python for HA. It has a very full featured and easy to use API. If you are even marginally comfortable with coding I highly recommend it.

Just to give you an idea. This is all it takes to do this in AppDaemon. It currently runs once a minute, and is hardcoded to the URL you wanted.

import my_appapi as appapi
import urllib.request
import json

class riverlevel(appapi.my_appapi):

  def initialize(self):
    # self.LOGLEVEL="DEBUG"
    self.log("riverlevel App")
    self.run_every(self.timer_handler,self.datetime(),60)


  def timer_handler(self,kwargs):
    url=str("http://environment.data.gov.uk/flood-monitoring/id/stations/1029TH")
    data=urllib.request.urlopen(url).read()
    jd=json.loads(data.decode("utf-8"))
    newlevel=jd["items"]["measures"][0]["latestReading"]["value"]
    self.log("River Level={}".format(newlevel))
    self.set_state("sensor.river_level",state=newlevel)                                            

Ok I got bored today and played some more. With just a little additional coding, I added support for US rivers.

I can add other attributes to show up in the card that pops up when you click on the sensor too. So I could theoretically add the flow rate, and any other information included in the json file too.

1 Like