Dictionary-like data from file to use in a script

After getting an IR blaster, I wanted to use it for having remote control possibility from HA. Sounds easy enough: for each remote, record the code from each button and save these in a file (below a snippet with one remote in JSON format). Somehow load this as a dictionary-like data structure into HA, and use a script to the IR-blaster via MQTT (see further below). The script gets the remote name and the button name as arguments and fetches the correct code to send.

The challenge now is that I seem to fail in loading the codes into some structure inside HA. File sensor seems promising, but doesn’t work as it loads only the last line. Removing all line breaks and making the file to be on one line doesn’t work as the length exceed 255 characters already with one remote, let alone with multiple. Same problem with command_line sensor. Some related answers were using using !include to assign template sensor attributes, but I didn’t get that working at all.

One option would be to type in each code into the scripts, but it just doesn’t feel right to manually repeat code that only differs in the data.

Right now I’m leaning towards putting the codes in a flat structure into secrets.yaml, but also that seems incorrect. These are not secrets and it would be really good to retain the hierarchical structure.

What would be the correct way of handling the situation in HA? I.e., how to get dictionary-like data from a file and use that in a script to get the actual data to be used to call a service? Somehow this doesn’t sound like a unique task, but still I failed to find a ready solution.

IR code snippet:

{
    "ir_codes": {
        "dac": {
            "power": "BZIjfRFHAkABA3oGRwLAAeADC8ABQBNAA0ABQAdAA8AB4AML4A8BQCPgDwMPpaWSI8AIRwL//5IjwAhHAg==",
            "vol_up": "Ba0jshFAAkABA38GQALAAeADC4ABAWoCQBNAA0ABAX8GQA8CagJA4AABBWoCfwZAAuANAeABG0Aj4AkDEWoCmaWtI8AIagL//60jwAhAAg==",
            "vol_down": "Ba4jpxFEAkABA30GRAKAAQFtAuABC+ABAUATQAMBRAJAH0ADAUQC4AMBQA9AA4ABAm0CROACAeABFwFEAkAL4AcDCaWlriO+CEQC///gCgcCCEQC",
        }
    }
}

Script sending codes (NB: this may still be buggy, since the development failed at an earlier phase):

ir_blaster_send:
  alias: "Send IR blaster raw code"
  sequence:
    - service: mqtt.publish
      data_template:
        topic: zigbee2mqtt/IR-blaster/set
        payload: "{{ {'ir_code_to_send': state_attr('sensor.ir_codes', remote_name ~ '.' ~ remote_button)} }}"
  mode: queued
  max: 10

One option is to set them up as a custom macro. In it’s basic form that would look something like:

#ir.jinja

{% set _ir_codes = {
  "dac": {
      "power": "BZIjfRFHAkABA3oGRwLAAeADC8ABQBNAA0ABQAdAA8AB4AML4A8BQCPgDwMPpaWSI8AIRwL//5IjwAhHAg==",
      "vol_up": "Ba0jshFAAkABA38GQALAAeADC4ABAWoCQBNAA0ABAX8GQA8CagJA4AABBWoCfwZAAuANAeABG0Aj4AkDEWoCmaWtI8AIagL//60jwAhAAg==",
      "vol_down": "Ba4jpxFEAkABA30GRAKAAQFtAuABC+ABAUATQAMBRAJAH0ADAUQC4AMBQA9AA4ABAm0CROACAeABFwFEAkAL4AcDCaWlriO+CEQC///gCgcCCEQC",
  },
  "receiver": {
      "power": "00001111001111",
      "vol_up": "00011000111111",
      "vol_down": "0001111001111111",
  } 
} %}

{% macro get_ir(name, button)%}
{{ _ir_codes[name][button] }}
{% endmacro %}

Then your script:

ir_blaster_send:
  alias: "Send IR blaster raw code"
  fields:
    remote_name:
      name: Remote
      required: true
    remote_button:
      name: Button
      required: true
  sequence:
    - service: mqtt.publish
      data:
        topic: zigbee2mqtt/IR-blaster/set
        payload: |
          {% from 'ir.jinja' import get_ir %}
          {{ {'ir_code_to_send': get_ir(remote_name, remote_button) } }}
  mode: queued
  max: 10

Why not use the remote learn once, then open the file and add the rest.
I’m fairly sure the format is about the same as you show here

Thank you! This works like a charm and has the flexibility of easy editing the jinja file. The only modification I ended up doing was streamlining the MQTT call into

  sequence:
    - service: mqtt.publish
      data_template:
        topic: zigbee2mqtt/IR-blaster/set/ir_code_to_send
        payload: |
          {% from 'ir.jinja' import get_ir %}
          {{ get_ir(remote_name, remote_button) }}