UI-Lovelace-Minimalist / UI

UI-Lovelace-Minimalist is a "theme" for HomeAssistant
https://ui-lovelace-minimalist.github.io/UI/
Other
1.66k stars 435 forks source link

Room Card: Temperature & Brightness together, plus custom temperature entity #1181

Open antonio1475 opened 1 year ago

antonio1475 commented 1 year ago

Is your enhancement request related to a problem? Please describe. I use Room Cards with the light entity defining the card color/state, so I have the light status/brightness. But, I also want to see the temperature when I have a sensor in that room. Currently, both cannot co-exist.

Describe the solution you'd like Ability to have both Brightness & Temperature, while keeping the light feature for the card (i.e. defining a custom entity for temp in that room).

Describe alternatives you've considered Here's the code I've arrived to:

  1. Add variable label_use_temperature_entity to the card variables (empty by default):

    variables:
    label_use_brightness: false
    label_use_temperature: false
    label_use_temperature_entity:
  2. Replace the code in label to no be if/else, but add the temperature if it exists, also adding the attributes/states from the new variable label_use_temperature_entity:

    label: |-
    [[[
      var label = variables.ulm_translation_state;
      var bri = Math.round(entity?.attributes?.brightness / 2.55);
    
      if (variables.label_use_brightness && entity?.state == "on" && entity?.attributes?.brightness != null) {
        label = (bri ? bri : "0") + "%";
      }
    
      if (variables.label_use_temperature ) {
        label += " | " + (states[variables.label_use_temperature_entity].attributes.current_temperature || states[variables.label_use_temperature_entity].attributes.temperature || states[variables.label_use_temperature_entity].state || entity?.attributes?.current_temperature || entity?.attributes?.temperature || entity?.state || '-') + (entity?.attributes?.unit_of_measurement || '°');
      }
    
      return label; 
    ]]]

Result: image

Additional context I haven't tested the code with entities other than lights.

This relates a bit to https://github.com/UI-Lovelace-Minimalist/UI/issues/656

PS: I do not know how to submit PRs and such, so I'm sharing the code for anyone to use or submit. @kepath I see that you did the last update to card_room so I'd be happy if you review this.

Cheers

DavidRosseljong commented 1 year ago

Result: image

@antonio1475 Hey. I don't know if I should ask here but I really like the room cards with 8 sensors. Could you share how you got it done, please? :)

antonio1475 commented 1 year ago

@antonio1475 Hey. I don't know if I should ask here but I really like the room cards with 8 sensors. Could you share how you got it done, please? :)

  1. Add a file named custom_card_room_8.yaml to /config/ui_lovelace_minimalist/custom_cards with this template:
    Click to expand code
---
custom_card_room_8:
  template:
    - "ulm_translation_engine"
  variables:
    label_use_brightness: false
    label_use_temperature: false
    label_use_temperature_entity:
    ulm_card_light_enable_popup: false
    ulm_card_tap_action: "toggle"
    ulm_card_hold_action: "more-info"
    ulm_card_double_tap_action: "more-info"
  tap_action:
    action: "toggle"
    haptic: "medium"
  double_tap_action:
    action: "more-info"
    haptic: "heavy"
  hold_action:
    action: "none"
    haptic: "success"
  color: "var(--google-grey-500)"
  size: "45%"
  aspect_ratio: "1/1"
  show_icon: true
  show_label: true
  show_name: true
  icon: "mdi:sofa-single"
  label: |-
    [[[
      var label = variables.ulm_translation_state;
      var bri = Math.round(entity?.attributes?.brightness / 2.55);

      if (variables.label_use_brightness && entity?.state == "on" && entity?.attributes?.brightness != null) {
        label = (bri ? bri : "0") + "%";
      }

      if (variables.label_use_temperature ) {
        label += " | " + (states[variables.label_use_temperature_entity].attributes.current_temperature || states[variables.label_use_temperature_entity].attributes.temperature || states[variables.label_use_temperature_entity].state || entity?.attributes?.current_temperature || entity?.attributes?.temperature || entity?.state || '-') + (entity?.attributes?.unit_of_measurement || '°');
      }

      return label; 
    ]]]
  state:
    - value: "unavailable"
      styles:
        custom_fields:
          notification:
            - border-radius: "50%"
            - border: "2px solid var(--card-background-color)"
            - width: "24.5px"
            - height: "24.5px"
            - position: "absolute"
            - left: "50%"
            - top: "50%"
            - transform: "translate(-50%,-50%)"
            - margin-top: "35%"
            - margin-left: "-35%"
            - line-height: 0
            - display: "grid"
            - background-color: "[[[ return 'rgba(var(--color-red),1)'; ]]]"
  styles:
    icon:
      - color: "rgba(var(--color-theme),0.2)"
      - margin-left: "12%"
    label:
      - justify-self: "start"
      - align-self: "start"
      - font-weight: "bold"
      - font-size: "0.75em"
      - filter: "opacity(40%)"
      - margin-left: "6px"
      - max-width: "[[[ return `calc(100% - (9px + ${!variables?.entity_1 && !variables?.entity_2 ? 5 : 0}px))`; ]]]"
      - text-overflow: "ellipsis"
      - overflow: "hidden"
      - margin-top: "[[[ return !variables?.entity_1 ? '-24%' : '-15%'; ]]]"
    name:
      - justify-self: "start"
      - align-self: "end"
      - font-weight: "bold"
      - font-size: "0.85em"
      - margin-left: "6px"
      - margin-bottom: "[[[ return !variables?.entity_1 ? (!variables?.entity_2 ? '15.8%' : '24%') : '15%'; ]]]"
      - max-width: "[[[ return `calc(100% - (12px + ${!variables?.entity_2 ? 5 : 0}px))`; ]]]"
      - text-overflow: "ellipsis"
      - overflow: "hidden"
    state:
      - justify-self: "start"
      - font-weight: "bold"
      - font-size: "0.75em"
      - filter: "opacity(40%)"
      - margin-left: "6px"
    img_cell:
      - background-color: "rgba(var(--color-theme),0.05)"
      - border-radius: "40%"
      - width: "62%"
      - height: "62%"
      - max-width: "none"
      - max-height: "none"
      - position: "absolute"
      - left: "-15%"
      - top: "51%"
      # - transform: "translate(-50%,-50%)"
      # - margin-top: "25%"
      # - margin-left: "-25%"
    grid:
      - grid-template-areas: "[[[ return !variables?.entity_1 ? (!variables?.entity_2 ? `'n n n' 'l l i3' 'i i i4'` : `'n n i2' 'l l i3' 'i i i4'`) : `'n n i5 i1' 'l l i6 i2' 'i i i7 i3' 'i i i8 i4'`; ]]]"
      - grid-template-columns: "[[[ return !variables?.entity_1 ? '1fr 1fr 1fr' : '1fr 1fr 1fr 1fr'; ]]]"
      - grid-template-rows: "[[[ return !variables?.entity_1 ? '1fr 1fr 1fr' : '1fr 1fr 1fr 1fr'; ]]]"
      - justify-items: "center"
    card:
      - border-radius: "20px"
      - box-shadow: "var(--box-shadow)"
      - padding: "5px"
      - transform: "translateZ(0)"
    custom_fields:
      i1: &widget_icon_room_8_styling
        - border-radius: "50%"
        - width: "87%"
        - height: "87%"
        - line-height: 0
        - display: "grid"
      i2: *widget_icon_room_8_styling
      i3: *widget_icon_room_8_styling
      i4: *widget_icon_room_8_styling
      i5: *widget_icon_room_8_styling
      i6: *widget_icon_room_8_styling
      i7: *widget_icon_room_8_styling
      i8: *widget_icon_room_8_styling
  custom_fields:
    notification: >
      [[[
        if (entity?.state == 'unavailable'){
          return '<ha-icon icon="mdi:exclamation" style="width: 50%; height: 50%; color: var(--primary-background-color);"></ha-icon>';
        }
      ]]]

    i1:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_1?.templates?.length) {
              templates.push(...variables.entity_1.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_1; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_1; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_1?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_1?.icon; ]]]"
        styles:
          mwc-ripple:
            - display: "none"

    i2:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_2?.templates?.length) {
              templates.push(...variables.entity_2.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_2; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_2; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_2?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_2?.icon; ]]]"

    i3:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_3?.templates?.length) {
              templates.push(...variables.entity_3.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_3; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_3; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_3?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_3?.icon; ]]]"

    i4:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_4?.templates?.length) {
              templates.push(...variables.entity_4.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_4; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_4; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_4?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_4?.icon; ]]]"

    i5:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_5?.templates?.length) {
              templates.push(...variables.entity_5.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_5; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_5; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_5?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_5?.icon; ]]]"

    i6:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_6?.templates?.length) {
              templates.push(...variables.entity_6.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_6; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_6; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_6?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_6?.icon; ]]]"

    i7:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_7?.templates?.length) {
              templates.push(...variables.entity_7.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_7; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_7; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_7?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_7?.icon; ]]]"

    i8:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_8?.templates?.length) {
              templates.push(...variables.entity_8.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_8; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_8; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_8?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_8?.icon; ]]]"

widget_icon_room_8:
  variables:
    tap_action:
      action: "toggle"
    double_tap_action:
      action: "more-info"
    hold_action:
      action: "none"
  tap_action:
    haptic: "medium"
    action: "[[[ return variables?.tap_action?.action ? variables.tap_action.action : 'none'; ]]]"
    entity: "[[[ return variables.tap_action.entity; ]]]"
    navigation_path: "[[[ return variables.tap_action.navigation_path; ]]]"
    url_path: "[[[ return variables.tap_action.url_path; ]]]"
    service: "[[[ return variables.tap_action.service; ]]]"
    service_data: "[[[ return variables.tap_action.service_data; ]]]"
  double_tap_action:
    haptic: "heavy"
    action: "[[[ return variables?.double_tap_action?.action ? variables.double_tap_action.action : 'more-info'; ]]]"
    entity: "[[[ return variables.double_tap_action.entity; ]]]"
    navigation_path: "[[[ return variables.double_tap_action.navigation_path; ]]]"
    url_path: "[[[ return variables.double_tap_action.url_path; ]]]"
    service: "[[[ return variables.double_tap_action.service; ]]]"
    service_data: "[[[ return variables.double_tap_action.service_data; ]]]"
  hold_action:
    haptic: "success"
    action: "[[[ return variables?.hold_action?.action ? variables.hold_action.action : 'none'; ]]]"
    entity: "[[[ return variables.hold_action.entity; ]]]"
    navigation_path: "[[[ return variables.hold_action.navigation_path; ]]]"
    url_path: "[[[ return variables.hold_action.url_path; ]]]"
    service: "[[[ return variables.hold_action.service; ]]]"
    service_data: "[[[ return variables.hold_action.service_data; ]]]"
  size: "15px"
  color: "var(--google-grey)"
  show_icon: true
  show_name: false
  styles:
    icon:
      - width: "50%"
      - height: "50%"
      - line-height: "0"
      - color: "rgba(var(--color-theme),0.2)"
    img_cell:
      - border-radius: "40%"
      - background-color: "rgba(var(--color-theme),0.05)"
    grid:
      - grid-template-areas: "'i'"
    card:
      - height: "100%"
      - box-shadow: "none"
      - padding: "0px"
      - border-radius: "40%"
      - transform: "translateZ(0)"

  1. Go to Developer Tools > Reload UI Lovelace Minimalist

  2. Adjust the room card in your ui-lovelace.yaml to that template and use the added features (see variables). Example with "Comedor" (incl. temp sensor & 8 switches).

Click to expand code ``` type: 'custom:button-card' template: - custom_card_room_8 - yellow_on name: Comedor entity: light.comedor icon: mdi:sofa-outline hold_action: haptic: success action: call-service service: script.convert_to_event service_data: command: 'comedor' variables: label_use_brightness: true label_use_temperature: true label_use_temperature_entity: "climate.home" entity_1: icon: mdi:air-conditioner entity_id: sensor.compresor_comedor_status templates: - red_on - yellow_idle tap_action: action: more-info entity: ac_scenes double_tap_action: action: more-info entity: switch.compresor_aire_acondicionado_comedor hold_action: action: more-info entity_2: entity_id: switch.purificador_comedor_local templates: - indigo_on entity_3: entity_id: media_player.samsungtv_smart icon: mdi:television templates: - teal_on tap_action: action: navigate navigation_path: remote-samsung double_tap_action: action: more-info hold_action: action: more-info entity: sensor.tele_comedor_cost_day entity_4: entity_id: light.tv_led icon: mdi:television-ambient-light templates: - yellow_on double_tap_action: action: more-info hold_action: action: call-service service: script.convert_to_event service_data: command: 'tele' entity_5: entity_id: switch.ventilador_comedor icon: mdi:ceiling-fan templates: - indigo_on entity_6: entity_id: switch.usb_comedor templates: - teal_on entity_7: entity_id: switch.ambientador_comedor templates: - pink_on entity_8: entity_id: input_number.pienso_diario icon: mdi:cat tap_action: action: more-info double_tap_action: action: navigate navigation_path: /config/devices/device/9402c16b2d2c6531d7de7e69ea45cf1f hold_action: action: call-service service: button.press service_data: entity_id: button.pienso_lily_quick_feed ```

image

DavidRosseljong commented 1 year ago

@antonio1475 Thank you very much!! :-)