Ouvrir un thermostat en cliquant sur une carte de température

Salut @Integra

Je suis sur ce problème depuis hier mais je n’ai pas trouvé de solution fonctionnelle (chatGPT et grok non plus d’ailleurs :grin: ). Le problème a déjà été évoqué sur le github. Il semble qu’il soit impossible de concaténer du texte avec le résultat du helpers, car celui ci n’est pas donné sous forme de texte.

Un calcul du lastseen manuel ne se met pas à jour automatiquement et donc n’apporte pas de solution viable. A l’ouverture de la carte le helpers et le calcul sont identiques mais au changement de valeur du helpers, le calcul ne se refait pas automatiquement. Il faudrait rafraichir la carte toutes les secondes… :

type: custom:button-card
entity: sensor.allee_du_garage_thermometre_last_seen
show_icon: false
show_name: false
show_state: true
state_display: |
  [[[
    const lastSeen = entity.state;
    if (!lastSeen) return "Jamais vu";
    const last = new Date(lastSeen);
    const now = new Date();
    const diffMs = now - last;
    const diffSec = Math.floor(diffMs / 1000);
    const diffMin = Math.floor(diffSec / 60);
    const diffH = Math.floor(diffMin / 60);
    const diffD = Math.floor(diffH / 24);

    if (diffSec < 60) return `Dernière M.A.J. il y a ${diffSec} s`;
    if (diffMin < 60) return `Dernière M.A.J. il y a ${diffMin} min`;
    if (diffH < 24) return `Dernière M.A.J. il y a ${diffH} h`;
    return `Dernière M.A.J. il y a ${diffD} j`;
  ]]]
custom_fields:
  update1: |
    [[[
      return helpers.relativeTime(entity.last_changed);
    ]]]
  update2: |
    [[[
      const rel = helpers.relativeTime(entity.last_changed);
      return `Dernière M.A.J. ${String(rel)}`;
    ]]]
  maj:
    card:
      type: custom:button-card
      entity: sensor.allee_du_garage_thermometre_last_seen
      show_icon: false
      show_name: false
      label: |
        [[[
          const rel = helpers.relativeTime(entity.last_changed);
          return `il y a ${rel.value} ${rel.unit}`;
        ]]]
      show_label: true
      styles:
        card:
          - border: none
        label:
          - font-size: 18px
          - color: blue
          - align-self: start
          - justify-self: start
styles:
  card:
    - aspect-ratio: 1/1
  state:
    - font-size: 18px
    - color: black
    - align-self: start
    - justify-self: start
    - padding-left: 50px
  custom_fields:
    update1:
      - font-size: 18px
      - color: red
      - align-self: start
      - justify-self: start
      - position: absolute
      - left: 50px
      - top: 80px
    update2:
      - font-size: 18px
      - color: green
      - align-self: start
      - justify-self: start
      - position: absolute
      - left: 50px
      - top: 160px
    maj:
      - position: absolute
      - left: 50px
      - top: 240px

En définitive, deux custom_fields semble être la seule solution fonctionnelle.

1 « J'aime »

Salut,
tu as essayé avec l’option triggers_update ?

Ou sur la beta v6.1.0-dev.2 l’option est automatique.

Citation
triggers_update is not required anymore, all entities used in JS templates are now discovered automatically.

Hello,

Je ne sais pas si j’ai tout suivi, mais le triggers update ça fonctionne très bien pour un affichage temps réel des données dans la button card, c’est ce que j’utilise dans mon template de carte esp

dès qu’une entité change de valeur la carte est recalculée

  esp:
    card:
      type: custom:button-card
      triggers_update:
        - '[[input_select_temp_hum_lux]]'
        - '[[entity_temp]]'
        - '[[entity_hum]]'
        - '[[entity_lux]]'
        - '[[entity_radar]]'
        - update.esphome_update
      show_name: false

1

image

A1

cdt

1 « J'aime »

Tout d’abord merci @btncrd pour le temps accordé !

Ça me rassure car on en est arrivé à la même conclusion ! J’étais également tombé sur l’issue Github qui date déjà d’un petit moment de mémoire, et j’ai voulu malgré tout forcer, et pareil j’ai même demandé de l’aide en dernier recours à l’IA qui me faisait tourner en rond… donc sans succès (données complexes et non textuelles > chercher plus loin dans la table => erreur et on recommence).

J’avais aussi remarqué ce phénomène car j’avais essayé le calcul manuel également, puis bon finalement j’ai opté pour scinder ça en deux custom_fields faute de mieux et ma foi ça fonctionne.

l’option triggers_update va être obsolète à partir de la v7 de button-card.

1 « J'aime »

J’essai de comprendre tout ce que vous dites mais j’avoue avoir encore du mal à tout bien saisir. Cela me fait une nouvelle poste d’amélioration.
Pour revenir à la carte, il y aurait-il une possibilité pour que le cercle reste centré quelque soit l’écran ou dois-je créer une page pour chaque écran?
J’ai modifier le code la semaine dernière sur un PC portable, tout est parfait. Soucis, sur ma tablette murale chez moi, c’est décalé et sur mon écran PC fixe aussi.

je crois que c’est un peu le problème des custom_fields suivant la taille de l’écran. Appart faire des cartes spécifiques suivant l’écran (modifier le top et left du custom_field), je ne pense pas qu’il y ait de solution.
Peu être @btncrd, connais une solution.

Bonjour @Othar

Voilà ce que donne la carte sur PC :

et sur téléphone portable (Companion) :

Le custom_fields “apex” reste centré sur la carte support.

styles:
  card:
    - aspect-ratio: 1/1.6
    - width: 180px
    - position: relative
    - background-color: "#1C1C1C"
  custom_fields:
    apex:
      - position: absolute
      - display: flex
      - justify-content: center
      - align-items: center
      - top: 29%
      - left: 50%
      - transform: translate(-50%, -50%)
      - width: 85%
      - height: 85%
      - overflow: visible
      - "--ha-card-border-width": 0
      - "--ha-card-background": transparent

Ce sont la paramètres “display: flex”, “justify-content: center”, “align-items: center” et “transform: translate(-50%, -50%)” qui permettent de garder le centrage du custom_fields.

Voici le code complet actuel de la carte (je vais ajouter un custom_fields pour le link quality) :

type: custom:button-card
entity: sensor.perron_thermometre_temperature
show_icon: false
show_state: false
show_name: false
custom_fields:
  room:
    card:
      type: custom:button-card
      icon: mdi:bed-double
      show_label: true
      label: Parents
      styles:
        card:
          - border: none
          - background: transparent
          - width: 180px
        icon:
          - width: 20px
          - color: rgba(255,255,255,0.75)
        label:
          - font-size: 11px
          - font-style: italic
          - color: rgba(255,255,255,0.75)
  temp:
    card:
      type: custom:button-card
      entity: sensor.perron_thermometre_temperature
      icon: mdi:thermometer
      show_state: true
      show_name: false
      state_display: |
        [[[
          return parseFloat(entity.state).toFixed(1) + '°';
        ]]]
      layout: icon_state
      numeric_precision: 1
      styles:
        card:
          - width: 82px
          - font-style: italic
          - border: none
          - background: transparent
        icon:
          - width: 18px
          - color: "#7dc8ff"
        state:
          - color: rgba(255,255,255,0.75)
          - font-size: 18px
  hum:
    card:
      type: custom:button-card
      entity: sensor.perron_thermometre_humidity
      icon: mdi:water
      show_state: true
      show_name: false
      layout: icon_state
      numeric_precision: 1
      styles:
        card:
          - width: 70px
          - font-style: italic
          - border: none
          - background: transparent
        icon:
          - width: 15px
          - color: "#7dc8ff"
        state:
          - color: rgba(255,255,255,0.75)
          - font-size: 13px
  battery:
    card:
      type: custom:button-card
      show_name: false
      show_label: true
      layout: icon_label
      icon: |-
        [[[
          var entity = states['sensor.perron_thermometre_battery'];
          if (!entity || entity.state === 'unavailable' || entity.state === 'unknown') 
            return 'mdi:battery-alert-variant-outline';
          var battery = parseInt(entity.state);
          if (isNaN(battery) || battery < 1)
            return 'mdi:battery-alert-variant-outline';
          if (battery <= 10)
            return 'mdi:battery-10';
          if (battery <= 20)
            return 'mdi:battery-10';
          if (battery <= 70)
            return 'mdi:battery-50';
          return 'mdi:battery';
        ]]]
      label: |
        [[[
          var entity = states['sensor.perron_thermometre_battery'];
          if (entity && entity.state !== 'unavailable' && entity.state !== 'unknown') {
            return entity.state + '%';
          }
          return '';
        ]]]
      styles:
        card:
          - border: none
          - background: transparent
          - aspect-ratio: 1/1
          - border-radius: 0
          - width: 50px
        icon:
          - color: |-
              [[[
                var entity = states['sensor.perron_thermometre_battery'];
                if (!entity || entity.state === 'unavailable' || entity.state === 'unknown') 
                  return 'lightgrey';
                var battery = parseInt(entity.state);
                if (isNaN(battery) || battery < 1)
                  return 'lightgrey';
                if (battery <= 10)
                  return 'darkred';
                if (battery <= 20)
                  return 'red';
                if (battery <= 70)
                  return 'orange';
                return 'green';
              ]]]
          - width: 100%
        label:
          - font-size: 10px
          - color: |-
              [[[
                var entity = states['sensor.perron_thermometre_battery'];
                if (!entity || entity.state === 'unavailable' || entity.state === 'unknown') 
                  return 'lightgrey';
                var battery = parseInt(entity.state);
                if (isNaN(battery) || battery < 1)
                  return 'lightgrey';
                if (battery <= 10)
                  return 'darkred';
                if (battery <= 20)
                  return 'red';
                if (battery <= 70)
                  return 'orange';
                return 'green';
              ]]]
          - padding-top: 3px
          - margin-left: "-10px"
  update_text: |
    [[[ return 'Dernière M.A.J.'; ]]]
  update_time: |
    [[[ return helpers.relativeTime(entity.last_changed); ]]]
  apex:
    card:
      type: custom:apexcharts-card
      chart_type: radialBar
      series:
        - entity: sensor.perron_thermometre_temperature
          max: 40
          color: "#00FF00"
          show:
            legend_value: false
        - entity: sensor.perron_thermometre_humidity
          max: 100
          color: "#FEFEFE"
          show:
            legend_value: false
      apex_config:
        plotOptions:
          radialBar:
            offsetY: 0
            hollow:
              size: 70%
            dataLabels:
              name:
                show: false
              value:
                show: false
            track:
              dropShadow:
                enabled: true
                top: 3
                left: 0
                blur: 4
                opacity: 0.25
              strokeWidth: 75%
              margin: 3
        fill:
          type: gradient
          gradient:
            type: vertical
            gradientToColors:
              - "#E73E01"
              - "#0F9DE8"
            stops:
              - 0
              - 100
        legend:
          show: false
        chart:
          height: 100%
  graph:
    card:
      type: custom:mini-graph-card
      name: Parents
      hours_to_show: 24
      points_per_hour: 1
      hour24: true
      line_width: 5
      decimals: 1
      entities:
        - entity: sensor.perron_thermometre_temperature
          name: Temp.
          color: "#2a75cf"
        - entity: sensor.perron_thermometre_humidity
          color: "#ffc04c"
          name: Humidité
      show_line: true
      show_points: true
      show_legend: true
      y_axis: secondary
      show:
        fill: true
        graph: line
        icon: false
        name: false
        state: false
        labels: false
        extrema: true
        average: true
        icon_adaptive_color: false
        labels_secondary: false
        align_icon: right
        align_state: left
      font_size: 85
styles:
  card:
    - aspect-ratio: 1/1.6
    - width: 180px
    - position: relative
    - background-color: "#1C1C1C"
  custom_fields:
    apex:
      - position: absolute
      - display: flex
      - justify-content: center
      - align-items: center
      - top: 29%
      - left: 50%
      - transform: translate(-50%, -50%)
      - width: 85%
      - height: 85%
      - overflow: visible
      - "--ha-card-border-width": 0
      - "--ha-card-background": transparent
    room:
      - position: absolute
      - display: flex
      - justify-content: center
      - align-items: center
      - top: 17%
      - left: 50%
      - transform: translate(-50%, -50%)
    temp:
      - position: absolute
      - display: flex
      - justify-content: center
      - align-items: center
      - top: 22%
      - left: 44px
    hum:
      - position: absolute
      - display: flex
      - justify-content: center
      - align-items: center
      - top: 30%
      - left: 50px
    battery:
      - position: absolute
      - right: 0%
      - top: "-3%"
    update_text:
      - position: absolute
      - top: 54%
      - left: 8px
      - color: rgba(255,255,255,0.75)
      - font-size: 11px
      - font-style: italic
    update_time:
      - position: absolute
      - top: 54%
      - right: 8px
      - color: rgba(255,255,255,0.75)
      - font-size: 11px
      - font-style: italic
    graph:
      - position: absolute
      - bottom: 0%
      - left: 0%
      - "--ha-card-border-width": 0
      - "--ha-card-background": transparent
      - "--primary-text-color": rgba(255,255,255, 0.75)
      - "--mini-graph-card-legend-font-size": 10px
1 « J'aime »