Template sensor attributes: Inject all attributes via json dictionary

I have the following working template sensor - additional 14 sensors more.with the same structure

    sensor:
      - name: 201_flur_moldAlarm
        unique_id: 201_flur_moldAlarm
        #friendly_name: "201_Flur-moldAlarm"
        icon: "mdi:water-percent-alert"
        state: "{{ moldAlarm }}"
        attributes:
          last_updated: "{{ t }}"
          advisory: "{{ advisory }}"
          advisory_dehumidifier: "{{ dehumidifierAdvisory }}"
          advisory_heating: "{{ heatingAdvisory }}"
          advisory_ventilation: "{{ ventilationAdvisory }}"
          wallsurface_temperature: "{{ wallSurfaceTemperature }}"
          wallsurface_humidity: "{{ wallSurfaceHumidity }}"
          wallsurface_humidity_max: "{{ maxWallSurfaceHumidity }}"
          insulation_factor: "{{ insulationKCalculated}}"
          insulation_factor_estimated: "{{ insulationK }}"
          indoor_temp_heating_target: "{{ indoor_temp_heating_target }}"
          indoor_temp: "{{ indoorTemp }}"
          indoor_humidity: "{{ indoorRelHumidity }}"
          indoor_wall_temp: "{{ indoorWallTemp }}"
          indoor_humidity_absolute: "{{ indoorAbsHumidity }}"
          indoor_dew_point: "{{ indoorDewPoint }}"
          outdoor_temp: "{{ outdoorTemp }}"
          outdoor_humidity: "{{ outdoorRelHumidity }}"
          outdoor_humidity_absolute: "{{ outdoorAbsHumidity }}"
          outdoor_dew_point: "{{ outdoorDewPoint }}"

I’ve created a marco which will output a JSON object (Result type: dict):

{
  "last_updated": "2024-07-18T11:27:36.889855+02:00",
  "advisory": "\n\n  \nVentilation possible\n  \n\n",
  "advisory_dehumidifier": "\n\nOn\n\n",
  "advisory_heating": "\n\n\n\n  \n  \n  \n   \n-8.010810810810812\n  \n  \n\n",
  "advisory_ventilation": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nNo\n\n",
  "wallsurface_temperature": 19.369999999999997,
  "wallsurface_humidity": 78.90809816947974,
  "wallsurface_humidity_max": 71.3542036519378,
  "insulation_factor": -3.8111111111111207,
  "insulation_factor_estimated": 0.74,
  "indoor_temp_heating_target": 20.5,
  "indoor_temp": 23.7,
  "indoor_humidity": 61,
  "indoor_wall_temp": 19.369999999999997,
  "indoor_humidity_absolute": 13.0490577027299,
  "indoor_dew_point": 15.7521871827347,
  "outdoor_temp": 22.8,
  "outdoor_humidity": 85.4,
  "outdoor_humidity_absolute": 17.3333339825414,
  "outdoor_dew_point": 20.2188904140976
}

Trying to substitute above attributes with the JSON Object is failing:

    sensor:
      - name: 101_buero_moldAlarm
        unique_id: 101_buero_moldAlarm
        #friendly_name: "101_Buero-moldAlarm"
        icon: "mdi:water-percent-alert"
        state: "{{ moldAlarm }}"
        attributes: >-
            {% from '036-mold-indicator.jinja' import moldIndicatorAttributes %}
            {{ moldIndicatorAttributes(insulationK, indoor_temp_heating_target, indoorTempt)|from_json }}
Logger: homeassistant.config
Source: config.py:590
First occurred: 11:19:40 (2 occurrences)
Last logged: 11:19:42

Invalid config for 'template' at packages/mold-indicator-package.yaml, line 102: expected a dictionary for dictionary value 'sensor->0->attributes', got "{% from '036-mold-indicator.jinja' import moldIndicatorAttributes %} {{ moldIndicatorAttributes(insulationK, indoor_temp_heating_target, indoorTemp, indoorRelHumidity, indoorWallTemp, indoorAbsHumidity, indoorDewPoint, outdoorTemp, outdoorRelHumidity, outdoorAbsHumidity, outdoorDewPoint) }}"

Any help is highly appreciated - Thanks

YAML is constructed of key / value pairs. key: value

The attributes key is expecting a dictionary of key: value pairs.

You can only template the value not the keys. Or to put it another way, you can’t template YAML, only values.

e.g.

valid:

attributes: 
  my_key: "{{ my_template }}"
  my_second_key: "{{ another_tempalte }}"

invalid:

attributes: >
  {{ my_template }}

You are trying to template all the YAML, not just the value part of key / value pairs.

Thanks for your clarification!

this will end in the following:

template:
  - trigger:
      - platform: state
        entity_id:
          - sensor.hm_tc_it_wm_w_eu_oeq0301997_temperature
          - sensor.hm_tc_it_wm_w_eu_oeq0301997_humidity
          - sensor.1_owd11
          - sensor.1_owd12
          - sensor.hm_wds10_th_o_oeq0087385_temperature
          - sensor.310_garten_wetter_humidity_bme280
        not_from:
          - "unknown"
          - "unavailable"
          - "none"
        not_to:
          - "unknown"
          - "unavailable"
          - "none"
    action:
      - variables:
          #
          # Adapt to room and outdoor sensors
          #
          insulationK: "{{ 0.74 }}"
          indoor_temp_heating_target: "{{ 20.5 }}"
          #
          indoorTemp: "{{ states('sensor.hm_tc_it_wm_w_eu_oeq0301997_temperature')|float(1) }}"
          indoorRelHumidity: "{{ states('sensor.hm_tc_it_wm_w_eu_oeq0301997_humidity')|float(1) }}"
          indoorWallTemp: "{{ ((states('sensor.1_owd11')|float(1) + states('sensor.1_owd12')|float(1)) /2)|float(1) }}"
          indoorAbsHumidity: "{{ states('sensor.101_buero_thermal_comfort_absolute_humidity')|float(1) }}"
          indoorDewPoint: "{{ states('sensor.101_buero_thermal_comfort_dew_point')|float(1) }}"
          outdoorTemp: "{{ states('sensor.hm_wds10_th_o_oeq0087385_temperature')|float(1) }}"
          outdoorRelHumidity: "{{ states('sensor.310_garten_wetter_humidity_bme280')|float(1) }}"
          outdoorAbsHumidity: "{{ states('sensor.301_hauszugang_thermal_comfort_absolute_humidity')|float(1) }}"
          outdoorDewPoint: "{{ states('sensor.301_hauszugang_thermal_comfort_dew_point')|float(1) }}"
          #
          var: >-
            {% from '036-mold-indicator.jinja' import moldIndicatorAttributes %}
            {{ moldIndicatorAttributes(insulationK, indoor_temp_heating_target, indoorTemp, indoorRelHumidity, indoorWallTemp, indoorAbsHumidity, indoorDewPoint, outdoorTemp, outdoorRelHumidity, outdoorAbsHumidity, outdoorDewPoint)|from_json }}
    sensor:
      - name: 101_buero_moldAlarm
        unique_id: 101_buero_moldAlarm
        #friendly_name: "101_Buero-moldAlarm"
        icon: "mdi:water-percent-alert"
        state: "{{ var.mold_alarm }}"
        attributes:
          last_updated: "{{ var.last_updated }}"
          advisory: "{{ var.advisory }}"
          advisory_dehumidifier: "{{ var.advisory_dehumidifier }}"
          advisory_heating: "{{ var.advisory_heating }}"
          advisory_ventilation: "{{ var.advisory_ventilation }}"
          wallsurface_temperature: "{{ var.wallsurface_temperature }}"
          wallsurface_humidity: "{{ var.wallsurface_humidity }}"
          wallsurface_humidity_max: "{{ var.wallsurface_humidity_max }}"
          insulation_factor: "{{ var.insulation_factor }}"
          insulation_factor_estimated: "{{ insulationK }}"
          indoor_temp_heating_target: "{{ indoor_temp_heating_target }}"
          indoor_temp: "{{ indoorTemp }}"
          indoor_humidity: "{{ indoorRelHumidity }}"
          indoor_wall_temp: "{{ indoorWallTemp }}"
          indoor_humidity_absolute: "{{ indoorAbsHumidity }}"
          indoor_dew_point: "{{ indoorDewPoint }}"
          outdoor_temp: "{{ outdoorTemp }}"
          outdoor_humidity: "{{ outdoorRelHumidity }}"
          outdoor_humidity_absolute: "{{ outdoorAbsHumidity }}"
          outdoor_dew_point: "{{ outdoorDewPoint }}"

Not short as expected:

  • but introducing action variables and

  • custom jinja templates

  • reduce code redundancies ~30%,

  • much more easier to maintain and

  • much more readable …

Thanks again!

1 Like

Nice solution!

With the exception of the var variable, the other ones defined in action serve to create more code, not less.

var is referenced by multiple attributes (one-to-many), so it helps to reduce code, whereas the others are referenced once (one-to-one) so they’re unnecessary duplicates.