Transform JSON for further use

I use GitHub - mampfes/ha_epex_spot: Adds EPEX Spot data to Home Assistant. to get the price data for electricity. I use this to find the 4 cheapest hours of a day.

As you can imagine, sometimes it’s 4 disjoint hours, and sometimes some or all hours are joint.

I want to write an automation that starts some appliances 1 min after the cheapest hour/range starts (just to make sure I fall into the intended range). And ends 1 minute before the hour/range ends (again, just to be sure I fall within the intended range).

The problem that I’m currently having is when there are hours that are actually joint and therefore sequential, the appliances turn off for two minutes. This is fine for most, but for my boiler it might be not. The boiler can pull ~11A. Which demands quite a lot from the electric contactor.

So what I wanted to do is to take that json and run it through a function that merges the sequential hours into a range.

I wrote this python script[1] to do just that. Then I tried to write it in jinja2, but it does not work. It also feels wrong asking a template engine to do that. So I was wondering. Do you all just deal with jinja2 or is there a better way?

[1] SuperShockingPagerecognition - Replit

import json

data = [
    {'start_time': '2024-03-22T02:00:00+01:00', 'end_time': '2024-03-22T03:00:00+01:00'},
    {'start_time': '2024-03-22T11:00:00+01:00', 'end_time': '2024-03-22T12:00:00+01:00'},
    {'start_time': '2024-03-22T12:00:00+01:00', 'end_time': '2024-03-22T13:00:00+01:00'},
    {'start_time': '2024-03-22T13:00:00+01:00', 'end_time': '2024-03-22T14:00:00+01:00'},
    {'start_time': '2024-03-23T10:00:00+01:00', 'end_time': '2024-03-23T11:00:00+01:00'},
    {'start_time': '2024-03-23T11:00:00+01:00', 'end_time': '2024-03-23T12:00:00+01:00'},
    {'start_time': '2024-03-23T13:00:00+01:00', 'end_time': '2024-03-23T14:00:00+01:00'},
    {'start_time': '2024-03-23T14:00:00+01:00', 'end_time': '2024-03-23T15:00:00+01:00'}
]

print("Before: ")
print(json.dumps(data, indent=2))
print()

new_data = []

current_region = data[0]
data = data[1:]

for region in data:
    if region['start_time'] == current_region['end_time']:
        current_region['end_time'] = region['end_time']
    else:
        new_data.append(current_region)
        current_region = region

# add last case as it always gets lost
new_data.append(current_region)

print("After: ")
print(json.dumps(new_data, indent=2))
print()

[2]

{% set data = state_attr('binary_sensor.boiler', 'data') %}
{% set newdata = [] %}
{% set current_region = data[0] %}

# remove first element from data
{% set data = data[1:] %}

{% for region in data %}
  {% set region_start = region.start_time | as_datetime %}
  {% set region_end = region.end_time | as_datetime %}
  {% set current_region_end = current_region.end_time | as_datetime %}

  {% if region_start == current_region_end %}
    {% set current_region = current_region.copy() %}
    {% set current_region = current_region.update({'end_time': region_end.isoformat()}) %}
  {% else %}
    {% set newdata = newdata + [current_region] %}
    {% set current_region = region %}
  {% endif %}
{% endfor %}

{% set newdata = newdata + [current_region] %}

{{ newdata }}

Likely you could do it with jq which is installed in home assistant. I use it extensively to manipuate JSON into JSON.

Where do you use it? In the template? Or is there Building Block that can be used for that?

Read through this post How to extract data from JSON (again)

Here is a complex example that reorganizes all the Insteon data into a completely different structure

See sensor.yaml

1 Like

Thanks for the answer, I think I will try it that way.