thomasloven / hass-lovelace_gen

🔹 Improve the lovelace yaml parser for Home Assistant
MIT License
209 stars 22 forks source link

Feature: Access globals from Jinja Templates #57

Open PeteRager opened 7 months ago

PeteRager commented 7 months ago

Feature: have the Lovelace global definitions be available in HA templates and automations. This would allow the metadata to be used in automations (or anywhere Jinja is used). I'm willing to do the work.

Use Case: I'm using this metadata to create an object model as part of the process of generating config.

Here is an example of a light control loaded into Lovelace Gen globals (which allows the UI to be autogenerated)

- name: basement_stairs
  type: switch
  targets: basement_stairs
  triggers: binary_sensor.basement_door_open,binary_sensor.basement_motion_detected 
  occupancy: binary_sensor.basement_rf_motion_detected,binary_sensor.basement_motion_detected,binary_sensor.ms_basement_door,binary_sensor.ms_basement_cam,binary_sensor.ms_furnace_cam,binary_sensor.basement_lf_motion_detected,binary_sensor.basement_lr_motion_detected 
  luminance: sensor.basement_luminance 
  delay: 
- name: basement_right
  type: switch
  targets: basement_right
  triggers: binary_sensor.basement_rf_motion_detected,binary_sensor.basement_motion_detected 
  occupancy: binary_sensor.basement_rf_motion_detected,binary_sensor.basement_motion_detected,binary_sensor.ms_basement_cam,binary_sensor.ms_furnace_cam,binary_sensor.basement_lf_motion_detected,binary_sensor.basement_lr_motion_detected 
  luminance: sensor.basement_luminance 
  delay:

So right now, I use that config to generate packages (templates and automations) using sed and yq to essentially replicate the package for each object to put in the right sensors, delays etc. So I can add a new light control in about 5 minutes. With the metadata available this process could be simplified.

Petro31 commented 7 months ago

This won't be possible anytime soon, lovelace_gen doesn't even have access to the state machine. I.e. all of the extra functionality that HA adds to Jinja2.

You can use {% raw %} and {% endraw %} to put templates into fields that won't be executed. The field has to support templates though.

The problem you'd need to overcome is that the configuration is loaded well before the templating engine has even started.

EDIT: IF you understand the above and you don't want to load macros that use the state machines, maybe we could implement a separate feature that acts like the custom_templates, but is not shared with the custom templates. Maybe lovelace_gen_templates or something along those lines. That would be a very nice feature for sure.

Petro31 commented 7 months ago

If you do the work. I'll help you test it.

PeteRager commented 7 months ago

Ok, so the challenge is getting the _global variable loaded and registered very early in the HA startup process before template compilation occurs which may occur before the integration is loaded. This is not unlike restarting HA with a Lovelace Gen screen open and the rendering fails (since the integration is not loaded)

I suppose another way would be to load the metadata into the state machine and then access it just like any other state machine data.

PeteRager commented 5 months ago

I got it working and it was a one-liner.

https://github.com/thomasloven/hass-lovelace_gen/pull/60

Basically what it does is create an entity called "lovelace_gen.data" with attributes that represent all of your top level keys -which is consistent with the way the _globals works

{{ states.lovelace_gen.data.attributes|list }}
[
  "av_equipment_list",
  "av_sonos_channel_list",
  "av_sonos_list",
  "aw_ramp_zone_list",
  "dr_list",
  "gd_list",
  "hs_list",
  "hv_cool_list",
  "hv_heat_list",
  "hv_view_list",
  "kg_list",
  "light_list",
  "modbus_list",
  "ms_group_list",
  "ms_list",
  "nw_list",
  "pw_voltage_list",
  "rs_service_list",
  "ts_list",
  "um_filter_list",
  "utility_fuel_list",
  "utility_power_list",
  "utility_water_list",
  "well_list",
  "well_view_list",
  "ws_list",
  "zwave_battery_list",
  "zwave_list"
]

Or more typically accessing a specific list - this is my door list

{{ state_attr("lovelace_gen.data","dr_list") }}
[
  {
    "name": "basement_door",
    "type": "interior",
    "entity_id": "binary_sensor.basement_door_open"
  },
  {
    "name": "workshop_door",
    "type": "interior",
    "entity_id": "binary_sensor.workshop_door_open"
  },
  {
    "name": "garage_door_1",
    "type": "exterior",
    "entity_id": "binary_sensor.garage_door_1_open"
  },
  {
    "name": "garage_door_2",
    "type": "exterior",
    "entity_id": "binary_sensor.garage_door_2_open"
  },
  {
    "name": "man_door",
    "type": "exterior",
    "entity_id": "binary_sensor.man_door_open"
  },
  {
    "name": "attic_door",
    "type": "interior",
    "entity_id": "binary_sensor.attic_door_open"
  },
  {
    "name": "studio_door",
    "type": "interior",
    "entity_id": "binary_sensor.studio_door_open"
  },
  {
    "name": "garage_door_1",
    "type": "open_duration",
    "entity_id": "binary_sensor.garage_door_1_open",
    "occupancy": "binary_sensor.garage_sensor_motion_detected"
  },
  {
    "name": "garage_door_2",
    "type": "open_duration",
    "entity_id": "binary_sensor.garage_door_2_open",
    "occupancy": "binary_sensor.garage_sensor_motion_detected"
  },
  {
    "name": "attic_door",
    "type": "open_duration",
    "entity_id": "binary_sensor.attic_door_open",
    "occupancy": "binary_sensor.ms_group_attic"
  }
]

or accessing a specific door (I may look at reworking my metadata to make this simpler)

{{ state_attr("lovelace_gen.data","dr_list")|selectattr("name","match","man_door")|list|first}}
{
  "name": "man_door",
  "type": "exterior",
  "entity_id": "binary_sensor.man_door_open"
}

Next step, I'm going to see how accessing this from auto-entites works.