Fuel Prices JSON undefined when rendering

Hi all,

Over the last couple of weeks, I’ve been getting errors returning on some (but not all) of the fuel prices that I’m pulling into Home Assistant.

The issues just seem to be occuring with the Tesco JSON file here: https://www.tesco.com/fuel_prices/fuel_prices_data.json.

Any ideas how I might fix it? Thanks!

2024-09-15 12:55:05.080 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: ‘value_json’ is undefined when rendering ‘{% set c = value_json.stations| selectattr(‘site_id’, ‘eq’, ‘gcnqu4gfqytc’) | first %}{{ ‘%.3f’ | format(c.prices.E10) }}’

1 Like

Likely, the actual http call fails for whatever reason.

To just avoid the error message you can check the availability of the JSON.
The state of the sensor will change to unavailable then.

Here’s an example how I use it.
If, for whatever reason, sensor.shelly_plug_1_power is not providing a numeric value, the operating status also switches to unavailable.

    - name: "Washing Machine Operting Status"
      unique_id: fa06a837-3f59-4995-9750-34c0b3a8db70
      device_class: running
      delay_on:
        seconds: 60
      delay_off:
        seconds: 60
      availability: >
        {{ is_number(states('sensor.shelly_plug_1_power')) }}
      state: >
        {{ states('sensor.shelly_plug_1_power')|float > 1 }}
      icon: mdi:washing-machine

I’d like to add to this as the Tesco sensor last worked on 6th September.

The REST resource is https://www.tesco.com/fuel_prices/fuel_prices_data.json and my template is

value_template: "{% set station = value_json.stations | selectattr('site_id', 'eq', 'gcjcty9xrcsj') | first %}{{ '%.2f' | format(station.prices.B7 / 100) }}"

The logged error is “Template variable error: ‘value_json’ is undefined”

Nothing changed for me (no updates or reboots) when the error started appearing. I have since updated and rebooted, and the error persists.

Checking https://jsonlint.com/ the JSON Tesco is returning is actually valid.

ASDA/Sainsburys/Esso fuel price sensors are unaffected.

In Developer tools the template works as expected:

{% set value_json = {"last_updated": "17/09/2024 11:19:01", "stations": [{"site_id": "gcx1zhq978t7", "brand": "TESCO", "address": "Tesco Express Doncaster Road Brayton Selby", "postcode": "YO8 9EG", "location": {"latitude": 53.768681, "longitude": -1.089549}, "prices": {"E5": 141.9, "E10": 131.9, "B7": 138.9}}, {"site_id": "gcrjktx96h1j", "brand": "TESCO", "address": "Tesco Express Nuthall Road Nottingham", "postcode": "NG8 6AU", "location": {"latitude": 52.984551, "longitude": -1.198109}, "prices": {"E5": 136.9, "E10": 129.9, "B7": 135.9}} ... TRUCATED ...]} %}

{% set station = value_json.stations | selectattr('site_id', 'eq', 'gcjcty9xrcsj') | first %}{{ '%.2f' | format(station.prices.B7 / 100) }}

So, as koying says, the actual http call fails for whatever reason… how can I debug that reason and get to the bottom of this ‘value_json’ is undefined error?

Looks like that api (now?) requires some headers to work:

- resource: 'https://www.tesco.com/fuel_prices/fuel_prices_data.json'
  headers:
    user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    accept-encoding: gzip, deflate, br, zstd
  sensor:
  - name: Tesco
    value_template: >
      {% set station = value_json.stations | selectattr('site_id', 'eq', 'gcjcty9xrcsj') | first %}
      {{ '%.2f' | format(station.prices.B7 / 100) }}  

I like the look of this, do you know if Shell offer the same? They’re local to me, but have 3 facilities across the town. So would be good to know which one has the lowest price for fuel.

Thanks,

Garry

I came across this post and was interested enough to try to run this in Node-RED. The UK Gov site has a full list of 15 fuel providers signed up to providing station location/price data in JSON format, so in Node-RED it was very easy to build a full list, poll the API for each brand, calculate distance from home for each station, and build a complete list of all stations with prices and distance. Did you know that the cheapest petrol is in Gibraltar, 1020 miles away?

However, the API for Tesco is proving difficult to get working.

The URL works just fine in a browser.

The URL did work, once, when first used in a Node-RED http request, thereafter it does not respond and I get a timeout.

Adding some headers to the call, such as

gets a response as ‘access denied - you do not have permission etc’.

I use Google Chrome, and by inspection pulled the complete set of 16 headers that Chrome uses to call the URL, then added all of them to my http request, and yes it now works. By carefully removing one header at a time, I have found which ones are required - missing any of these five gives me either access denied or a timeout error. (at least this is working at the moment…)

headers:
  accept: clubcard
  accept-encoding: points
  accept-language: spanglish
  user-agent: dark-glasses
  cookie: dough

You can see, from the header values that I am using, that nothing is actually being used, just someone at some point has messed about with something and the API URL (which goes through www-tesco-com) must be looking for the existence of certain headers before it both accepts and then forwards the request.

As they say, every little header helps.