Custom carte cover de mushroom / template

Niquel pour moi, je chercher a afficher une entité dans le bagde. Merci :+1:
tarif hphc

            mushroom-badge-icon:after {
              content: "{{ states('select.energie_quotidienne_xxxx')}}";
              position: absolute;
              display: flex;
              justify-content: center;
              align-items: center;
              {% if states('select.energie_quotidienne_xxxx') == 'hc' %}
              background: rgb(var(--rgb-green));
              {% else %}
              background: rgb(var(--rgb-red));
              {% endif %}
              color: white;
              font-weight: bolder;
              border-radius: 50%;
              top: 0px;
              left: 0px;
              font-size: 0.75em;
              height: 1.4em;
              width: 1.4em; 
            }        

Tiens au passage :

Salut :wave:
Oui le badges des templates ne supporte qu’un icône pour l’instant car la taille est très petite et le texte peut donc être compliqué à lire. De plus, en cas de texte long, ça peut vite donner un rendu très étrange.

J’essaie de garder un équilibre entre fonctionnalités et simplicité d’usage mais je peux comprendre que certains limitations peuvent être frustrantes :sweat_smile: Après oui pour tes personnalisations comme celle-ci il faut faire un peu de CSS.

En fait ce que je veux éviter c’est d’avoir une tonne d’options comme custom button card. D’ailleurs, j’ai construit Mushroom parce que ça m’agaçait de chercher dans toutes les options :sweat_smile: Je voulais juste un truc qui marche quite a faire quelques compromis.

Bonjour

Alors chez moi j’utilise l’affaire comme ceci :
image

Résumé
cards:
  - type: custom:mushroom-template-card
    primary: Etage
    tap_action:
      action: navigate
      navigation_path: bathroom
    hold_action:
      action: toggle
    double_tap_action:
      action: more-info
    fill_container: true
    layout: horizontal
    multiline_secondary: false
    secondary: |
      {% set all = expand('group.grp_pte_etage')| list -%}
      {% set closed = all | selectattr('state','eq','off')|list|count%}
      {% set open = all | selectattr('state','eq','on')|list|count%}
      Fermés : {{closed}} / Ouverts : {{open}}
    icon: |
      {% if is_state('group.grp_pte_etage', 'on') %} 
        mdi:door-open
      {% else %}
        mdi:door-closed
      {% endif %}
    icon_color: |
      {% if is_state('group.grp_pte_etage','on') %}
        red
      {% else %}
        green
      {% endif %}
    badge_icon: >-
      {% set all = expand('group.grp_pte_etage')| list -%}  {% set open1 = all |
      selectattr('state','eq','on')|list|count%} {% set closed1 = all |
      selectattr('state','eq','off')|list|count%}       {% if open1 == 1 %}
        mdi:numeric-1
      {% elif open1 == 2 %}
        mdi:numeric-2
      {% elif open1 == 3 %}
        mdi:numeric-3
      {% elif open1 == 4 %}
        mdi:numeric-4
      {% elif open1 == 5 %}
        mdi:numeric-5
      {% elif open1 == 6 %}
        mdi:numeric-6
      {% elif open1 == 7 %}
        mdi:numeric-7
      {% elif open1 == 8 %}
        mdi:numeric-8
      {% elif open1 == 9 %}
        mdi:numeric-9
      {% elif open1 == 10 %}
        mdi:numeric-10
      {% else %}
        mdi:numeric-5
      {% endif %}
    badge_color: |
      {% set all = expand('group.grp_pte_etage')| list -%} 
      {% set open = all | selectattr('state','eq','on')|list|count%}
      {% if open == 0 %}
        green
      {% else %}
        red
      {% endif %}
    card_mod:
      style: |
        :host {
          --mush-badge-icon-size: 0.95em;
          --mush-icon-size: 76px;
          height: 66px;
          margin-left: -18px !important;
        }
        mushroom-badge-icon {
          left: 60px;
          top: 6px;
        }

Oui, avec des icônes. La solution de @Herbs on peu mettre du texte ou chiffre et plusieurs caractère.
Ta solution ce base sur une icône, donc 1 caractère.
Et sa utilise les states d’une entités.

Hello,
J’ai un comportement étrange de la carte (j’ai repris le code de @jerome6994)
En mode édition, pas de problème :
image
Si je sors du mode édition, la pagination est dégueu:
image
le code :

type: custom:mushroom-template-card
primary: Ouvrants Salon
hold_action:
  action: toggle
double_tap_action:
  action: more-info
fill_container: true
layout: horizontal
multiline_secondary: false
secondary: |
  {% set all = expand('binary_sensor.ouvrants_salon')| list -%}
  {% set closed = all | selectattr('state','eq','off')|list|count%}
  {% set open = all | selectattr('state','eq','on')|list|count%}
  Fermés : {{closed}} / Ouverts : {{open}}
icon: |
  {% if is_state('binary_sensor.ouvrants_salon', 'on') %} 
    mdi:door-open
  {% else %}
    mdi:door-closed
  {% endif %}
icon_color: |
  {% if is_state('binary_sensor.ouvrants_salon','on') %}
    red
  {% else %}
    green
  {% endif %}
badge_icon: >-
  {% set all = expand('binary_sensor.ouvrants_salon')| list -%}  {% set open1 =
  all | selectattr('state','eq','on')|list|count%} {% set closed1 = all |
  selectattr('state','eq','off')|list|count%}       {% if open1 == 1 %}
    mdi:numeric-1
  {% elif open1 == 2 %}
    mdi:numeric-2
  {% elif open1 == 3 %}
    mdi:numeric-3
  {% elif open1 == 4 %}
    mdi:numeric-4
  {% elif open1 == 5 %}
    mdi:numeric-5
  {% elif open1 == 6 %}
    mdi:numeric-6
  {% elif open1 == 7 %}
    mdi:numeric-7
  {% elif open1 == 8 %}
    mdi:numeric-8
  {% elif open1 == 9 %}
    mdi:numeric-9
  {% elif open1 == 10 %}
    mdi:numeric-10
  {% else %}
    mdi:numeric-5
  {% endif %}
badge_color: |
  {% set all = expand('binary_sensor.ouvrants_salon')| list -%} 
  {% set open = all | selectattr('state','eq','on')|list|count%}
  {% if open == 0 %}
    green
  {% else %}
    red
  {% endif %}
card_mod:
  style: |
    :host {
      --mush-badge-icon-size: 0.95em;
      --mush-icon-size: 60px;
      height: 66px;
      margin-left: -18px !important;
    }
    mushroom-badge-icon {
      left: 50px;
      top: 6px;
    }

Je me réponds à moi-même : margin-left…
my bad, sorry

Salut,
merci pour c’est solution qui m’a permis d’avoir plus de 10 chiffres avec les icones.
j’avais fais ca, mais ta solution est top.

              badge_icon: |-
                {% set all = expand('group.grp_lumieres')| list -%} 
                {% set open1 = all | selectattr('state','eq','on')|list|count%}
                {% if open1 == 0 %}
                  mdi:numeric-0
                {% elif open1 == 1 %}
                  mdi:numeric-1        
                {% elif open1 == 2 %}
                  mdi:numeric-2
                {% elif open1 == 3 %}
                  mdi:numeric-3
                {% elif open1 == 4 %}
                  mdi:numeric-4
                {% elif open1 == 5 %}
                  mdi:numeric-5
                {% elif open1 == 6 %}
                  mdi:numeric-6
                {% elif open1 == 7 %}
                  mdi:numeric-7
                {% elif open1 == 8 %}
                  mdi:numeric-8
                {% elif open1 == 9 %}
                  mdi:numeric-9
                {% elif open1 == 10 %}
                  mdi:numeric-10
                {% elif open1 >= 11 %}
                  mdi:numeric-9-plus
                {% else %}
                  none
                {% endif %}

J’ai ajouter le changement de couleur du background pour le badge.

        mushroom-badge-icon:after {
          content: "{{ expand(states.group.grp_lumieres) | selectattr( 'state', 'eq', 'on') | list | count }}";
          position: absolute;
          display: flex;
          justify-content: center;
          align-items: center;
          {% if is_state('group.grp_lumieres','on') %}
            background: rgb(var(--rgb-red));
          {% else %}
            background: rgb(var(--rgb-green));
          {% endif %}
          font-weight: bold;
          border-radius: 50%;
          top: 0;
          width: 100%;
          height: 100%;
          font-size: 0.9em; 
        }  

Hello,

@jerome6994 , j’ai cette erreur qui apparait dans les journaux:

Error while processing template: Template<template=({% set all = expand('cover.all_covers'|lower) -%} {% set positions = all | map(attribute='attributes.current_position')|list-%} {% set moving = all | selectattr('state', 'in', ['opening','closing'])|list|count -%} {% set open = positions | reject("!=",100) |list |count -%} {% set closed = positions | reject("!=",0) |list |count -%} {% set other = positions|list|count - open - closed - moving -%}Fermés = {{ closed }} / Partiels = {{ other }} / Ouverts = {{ open }} {% if moving >0 -%} / Actifs ={{ moving }}{% endif %}) renders=118>
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 568, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2231, in _render_with_context
    return template.render(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
jinja2.exceptions.UndefinedError: 'None' has no attribute 'state'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 694, in async_render_to_info
    render_info._result = self.async_render(
                          ^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 570, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: UndefinedError: 'None' has no attribute 'state'

Tu aurais une idée du soucis stp?

Je te rajoute mon de code:

{% set all = expand('cover.all_covers'|lower) -%} {% set
                positions = all |
                map(attribute='attributes.current_position')|list-%} {% set
                moving = all | selectattr('state', 'in',
                ['opening','closing'])|list|count -%} {% set open = positions |
                reject("!=",100) |list |count -%} {% set closed = positions |
                reject("!=",0) |list |count -%} {% set other =
                positions|list|count - open - closed - moving -%}Fermés = {{
                closed }} / Partiels = {{ other }} / Ouverts = {{ open }} {% if
                moving >0 -%} / Actifs  ={{ moving }}{% endif %}

Merci à toi.

Bonjour

Je ne suis pas en posture de te répondre déjà parce que je suis sur téléphone et compliqué de faire des manip
Ensuite je ne regarde jamais les journaux donc je sais pas les corriger mais ça tourne :crazy_face:

Mon code en production :


type: custom:stack-in-card
cards:
  - type: custom:mushroom-template-card
    primary: CR 2450 - Mouvements
    tap_action:
      action: navigate
      navigation_path: bathroom
    hold_action:
      action: toggle
    double_tap_action:
      action: more-info
    fill_container: true
    layout: horizontal
    multiline_secondary: false
    icon: mdi:battery-medium
    icon_color: blue
    badge_icon: none
    badge_color: transparent
    card_mod:
      style: |
        :host {
          --mush-badge-icon-size: 0.95em;
          --mush-icon-size: 76px;
          height: 66px;
          margin-left: -24px !important;
        }
        mushroom-badge-icon {
          left: 60px;
          top: 6px;
        }
        ha-card {
          --card-primary-font-size: 18px;
          --card-secondary-font-size: 14px;
        }
        mushroom-badge-icon:after {
          content: "{{ expand(states.sensor.grp_batterie_cr2450) | list | count }}";
          position: absolute;
          display: flex;
          justify-content: center;
          align-items: center;
          background: rgb(var(--rgb-blue));
          color: var(--card-background-color);
          font-weight: bolder;
          border-radius: 50%;
          width: 100%;
          height: 120%;
          font-size: 0.8em; 
          top: 2px;
        }
card_mod:
  style: |
    ha-card {
      {%- set  nb = expand(states.sensor.grp_batterie_cr2450) | list | count -%}
      {% if nb < 25 %}
      background: red;
      {% else %}
      background: rgb(46, 64, 83);
      {% endif -%}
      box-shadow: none;
    }

Salut,

A mon avis dans le groupe cover.all_covers il y a un élément qui n’a pas d’état, qui n’est pas un volet, voire qui n’existe plus…

Hello,

Voici mon groupe de volets:

- platform: group
  name: all_covers
  entities:
    - cover.volet_chambre_jardin
    - cover.volet_chambre_terrasse
    - cover.volet_baie_suite
    - cover.volet_pano_p
    - cover.volet_sdb_p
    - cover.volet_entree
    - cover.volet_cuisine
    - cover.volet_fixe_terrasse
    - cover.volet_fixe_jardin
    - cover.volet_baie_3m
    - cover.volet_baie_2m

Pour moi c’est ok de ce coté la, il y a tous le monde.

Le template de la position des volets:

  - platform: template
    sensors:
      position_volets_all:
        friendly_name: "Position volets de tous les volets"
        unit_of_measurement: "%"
        value_template: >
          {% set ns = namespace(total = 0,  list= states['cover.all_covers'].attributes.entity_id ) %}
          {% set count =ns.list|count %}
          {%if count > 0 %}
            {%- for volet in ns.list %}
              {% set ns.total = ns.total + (states[volet.replace("cover.volet_", "sensor.position_")].state | int(default=0))  %} 
            {%- endfor %}
            {{ (ns.total / count) | round(0) }}
          {% else %}
           0
          {% endif %}

Ok et ce tout le monde est fonctionnel ?
C’est pas un souci de complétude de liste, mais des éléments que ça contient.
Tu peux faire un test en désactivant tous les volets sauf 1 par exemple

Alors je viens de remarquer un truc, dans mon mqtt_sensor.yaml, j’ai déclaré ça pour recuperer la position:

- name: "position_entree"
  state_topic: "nodered/volet/entree/get"
  unit_of_measurement: '%'

Et mes volets sont déclaré comme cela:

- platform: template
  covers:
    volet_entree:
      friendly_name: "Entrée"
      open_cover:
        service: mqtt.publish
        data_template:
          topic: 'nodered/volet/entree/set'
          payload: 'up'
      close_cover:
        service: mqtt.publish
        data_template:
          topic: 'nodered/volet/entree/set'
          payload: 'down'
      stop_cover:
        service: mqtt.publish
        data_template:
          topic: 'nodered/volet/entree/set'
          payload: 'stop'
      set_cover_position:
        service: mqtt.publish
        data_template:
          topic: 'nodered/volet/entree/set'
          payload: "{{position}}"

Je devrais pas merge les deux en un seul ?
Car le position_entree remonte bien le % d’ouverture mais pas le volet_entree

Donc c’est possiblement une explication de l’erreur, le code cherche justement à lister la position

{% set all = expand('cover.all_covers'|lower) -%}
{% set positions = all | map(attribute='attributes.current_position')|list-%}

Il faut que je change par ce sensor: position_volets_all
Comment cela ce traduit dans le code?

Humm… Je suis pas sur en voyant le nom que c’est la bonne solution, le code a besoin de volets AVEC des attributs position, pas uniquement des positions ou uniquement des volets

Avec ma carte minimalist, cela fonctionne:
image

- type: custom:button-card
  template: custom_card_cover_buttons
  variables:
    entity: cover.volet_entree
    position_ouvert: sensor.position_entree
    name: Entrée
    position: 84
Template
custom_card_cover:
    tap_action:
      action: more-info
    triggers_update: all
    icon: |
      [[[
          var icon = 'mdi:window-shutter';
          if (states[variables.position_ouvert].state == 0){
            var icon = 'mdi:window-shutter';
          } else
            var icon = 'mdi:window-shutter-open';
          return icon ;
      ]]]
    label: |-
      [[[ 
          var etat = "";
    
          if (states[variables.position_ouvert].state == 100)
              etat = 'Ouvert';
          else if (states[variables.position_ouvert].state == 0)
              etat = "Fermé";
          else
              etat = "Ouvert" + ' • ' + states[variables.position_ouvert].state + '%' ;
          
          return etat ;
          
      ]]]
    state:
      - operator: template
        value: |
          [[[
            return states[variables.position_ouvert].state != 0;
          ]]]
        styles:
          icon:
            - color: "rgba(var(--color-blue),1)"
          img_cell:
            - background-color: "rgba(var(--color-blue),0.2)"
custom_card_cover_buttons:
    variables:
      entity: '[[[ return variables.entity ]]]'
      name: '[[[ return variables.name ]]]'
    styles:
      card:
        - border-radius: 20px
        - box-shadow: var(--box-shadow)
        - padding: 12px
      grid:
        - grid-template-areas: '"item1" "item2"'
        - grid-template-columns: 1fr
        - grid-template-rows: min-content  min-content
        - row-gap: 12px
    custom_fields:
      item1:
        card:
          entity: '[[[ return variables.entity ]]]'
          name: '[[[ return variables.name ]]]'
          variables:
            position_ouvert: '[[[ return variables.position_ouvert ]]]'
          tap_action:
            action: none
          template:
            - icon_info
            - custom_card_cover
          type: custom:button-card
      item2:
        card:
          template: list_4_items
          type: custom:button-card
          custom_fields:
            item1:
              card:
                icon: mdi:arrow-up
                tap_action:
                  action: call-service
                  service: cover.open_cover
                  service_data:
                    entity_id: '[[[ return variables.entity ]]]'
                type: custom:button-card
                template: widget_icon
            item2:
              card:
                icon: mdi:pause
                tap_action:
                  action: call-service
                  service: cover.stop_cover
                  service_data:
                    entity_id: '[[[ return variables.entity ]]]'
                type: custom:button-card
                template: widget_icon
            item3:
              card:
                icon: mdi:menu
                tap_action:
                  action: call-service
                  service: cover.set_cover_position
                  service_data:
                    entity_id: '[[[ return variables.entity ]]]'
                    position: '[[[ return variables.position ]]]'
                type: custom:button-card
                template: widget_icon
            item4:
              card:
                icon: mdi:arrow-down
                tap_action:
                  action: call-service
                  service: cover.close_cover
                  service_data:
                    entity_id: '[[[ return variables.entity ]]]'
                type: custom:button-card
                template: widget_icon

Je sais pas si cela peu aider…

Les cartes (surtout les templates) c’est pas exactement le même mécanisme que les entités
A mon avis, tu vires (temporairement) le volet de l’entrée de la liste (et les autres volets qui sont dans la même cas).
L’objectif c’est d’avoir un groupe (aussi peut-il soit-il) qui permet de faire fonctionner le code, de trouver ensuite le(s) volet(s) qui cause le souci, pour pouvoir comparer les volets qui marchent et ceux qui ne marchent pas

Ben ils sont tous pareil mes volets.
Et même en individuel, je remarque que cela ne fonctionne pas avec la carte Mushroom. Même a l’appui sur un des bouton rien ne ce passe.