Faire des jauges de ce type

J’aimerai bien connaitre la méthode de mesurage (apparemment c’est un compteur Geiger : mesure en coups par minutes) mais vu la taille des sondes alpha d’un compteur Geiger traditionnel, je ne vois pas comment ils ont pu adapter ça à un appareil domestique.

Bonjour,

Je trouve cela très réussi, je suggère une amélioration : ajouter la valeur min et max du jour pour le capteur considéré :

Qu’en pensez vous ?

C’est en place sur les jauges de température :


Il suffit d’avoir un sensor qui récupère ces valeurs et de mettre dans le code de la carte « Radon » les custom_fields « min_temp_week » et « max_temp_week » (après le avoir renommés) :

  min_temp_week:
    card:
      type: custom:button-card
      icon: m3of:vertical-align-bottom
      show_name: false
      show_state: true
      layout: icon_state
      state_display: |
        [[[
          return parseFloat(states['sensor.salle_a_manger_temperature_min_semaine'].state).toFixed(1) + "°";
        ]]]
      styles:
        card:
          - width: 80px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - font-size: 1.2rem
          - align-self: end
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 600
        icon:
          - width: 20px
          - color: rgba(167,176,205,1.0)
  max_temp_week:
    card:
      type: custom:button-card
      icon: m3of:vertical-align-top
      show_name: false
      show_state: true
      layout: state_icon
      state_display: |
        [[[
          return parseFloat(states['sensor.salle_a_manger_temperature_max_semaine'].state).toFixed(1) + "°";
        ]]]
      styles:
        card:
          - width: 80px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - font-size: 1.2rem
          - align-self: end
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 600
          - padding-right: 100px
        icon:
          - width: 20px
          - color: rgba(167,176,205,1.0)

Sur la carte « Température extérieure », les sensors sont calibrés sur 30 jours.

EDIT : Merde, il faut que j’arrête et que j’aille prendre mes gouttes : j’intègre les améliorations avant même qu’elles ne soient demandées :rofl:

3 « J'aime »

Super, par contre j’ai rajouté bêtement le script que tu donnes et les min et max ne s’affichent pas, comment faut il faire ?

Tu as fait des sensors pour obtenir les valeurs ? Si oui, il faut ajouter le positionnement des custom_fields dans les styles. Donne moi ton code complet stp.

colle l’ensemble du code en mode formaté (</>) car là c’est pas exploitable

Le plus simple est de reprendre le code de la carte « Température intérieure » posté en 53/128 et d’y mettre tes capteurs, tu auras ainsi une structure correcte car là, en collant à la suite les blocs concernant les valeurs minimales et maximales, çe n’ira pas (tu n’as pas la position des deux nouveaux custom_fields dans les styles)

Parfait et encore bravo !!!

Reste à paramétrer un peu …

Tu crées pas mal de fois les constantes min, max, min_temp,min_max auxquelles tu donnes les mêmes valeurs, tu ne pourrais pas les déclarer en variable au début du script de la carte ?

Bonjour,

Très belle jauges. J’aime bien la version compact. Pouvez-vous partager le code pour la jauge d’humidité SVP?

Merci

@MichelJ ,

Le plus simple est de demander au concepteur des cartes, non ?

Après, c’est pas évident avec la solution mise sur un des posts du créateur du sujet :rofl:

1 « J'aime »

Il faut voir si la portée des variables va jusqu’aux custom_fields. Cela fonctionne pour des templates mais je ne suis sur de rien pour la portée carte parent → cartes filles.

disons que le compteur geiger est sur un autre ESP. ils sont regroupés sur la même carte, c’est tout.

c’est comme le compteur de puissance sur la prise connectée de ma pompe de relevage, c’est pas dans le même boitier, mais j’ai regrouppé ca dans ‹ environnement ›

Voici ce qu’a fiat l’IA pour mettre les variables en début de code, ça a l’air d’être ok :

type: custom:button-card
entity: sensor.temperature_salon
variables:
  v_min: 14
  v_max: 30
show_state: false
show_icon: false
show_name: false
tap_action: none
double_tap_action: none
hold_action: none
custom_fields:
  icon_and_name:
    card:
      type: horizontal-stack
      cards:
        - type: custom:button-card
          icon: mdi:thermometer
          styles:
            card:
              - aspect-ratio: 1/1
              - width: 50px
              - padding: 0
              - border: 4px solid rgba(167,176,205,1.0)
              - border-radius: 50%
              - background: none
            icon:
              - width: 90%
              - color: white
        - type: custom:button-card
          name: Température salon
          styles:
            card:
              - width: auto
              - padding: 0
              - border: none
              - border-radius: 0
              - background: none
            name:
              - font-size: 1.4rem
              - justify-self: start
              - color: white
              - font-weight: 500
              - padding-top: 6%
  dividing_line:
    card:
      type: custom:button-card
      styles:
        card:
          - width: 600px
          - height: 1px
          - padding: 0
          - border: 1px solid rgba(54,56,68,1.0)
          - border-radius: 0
          - background: none
          - overflow: hidden
  value_and_unit:
    card:
      type: horizontal-stack
      cards:
        - type: custom:button-card
          show_name: false
          show_icon: false
          show_state: true
          state_display: |
            [[[
              return parseFloat(entity.state).toFixed(1);
            ]]]
          styles:
            card:
              - width: auto
              - padding: 0
              - border: none
              - border-radius: 0
              - background: none
              - margin-right: "-10%"
            state:
              - color: white
              - font-size: 1.8rem
              - font-weight: 800
        - type: custom:button-card
          name: °C
          styles:
            card:
              - width: auto
              - padding: 0
              - border: none
              - border-radius: 0
              - background: none
              - margin-left: "-10%"
            name:
              - font-size: 1.2rem
              - align-self: start
              - justify-self: start
              - color: rgba(167,176,205,1.0)
              - font-weight: 800
              - padding-top: 40%
  bar:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - height: 12px
          - width: 360px
          - border-radius: 999px
          - border: 0
          - padding: 0px
          - background: >-
              linear-gradient(to right, rgba(0,0,255,1.0) 0%,
              rgba(0,165,255,1.0) 25%, rgba(0,255,0,1.0) 50%,
              rgba(255,255,0,1.0) 62.5%, rgba(255,165,0,1.0) 75%,
              rgba(255,0,0,1.0) 100%)
  cursor:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - width: 16px
          - height: 32px
          - border-radius: 999px
          - border: 4px solid rgba(42,45,54,1.0)
          - background-color: |
              [[[
                const minTemp = variables.v_min;
                const maxTemp = variables.v_max;
                const temp = Number(entity.state) || minTemp;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100); 
                const stops = [
                  { p: 0,    c: [0, 0, 255]    },
                  { p: 25,   c: [0, 165, 255]  },
                  { p: 50,   c: [0, 255, 0]    },
                  { p: 62.5, c: [255, 255, 0]  },
                  { p: 75,   c: [255, 165, 0]  },
                  { p: 100,  c: [255, 0, 0]    }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
  min_val:
    card:
      type: custom:button-card
      name: "[[[ return variables.v_min + '°C' ]]]"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - background: none
        name:
          - font-size: 1.0rem
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
          - white-space: nowrap
  max_val:
    card:
      type: custom:button-card
      name: "[[[ return variables.v_max + '°C' ]]]"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - background: none
        name:
          - font-size: 1.0rem
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
          - white-space: nowrap
  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const temp = Number(entity.state) || 0;
          if (temp < 18) return "Trop froid";
          if (temp < 20) return "Frais mais acceptable";
          if (temp < 22) return "Confort idéal";
          if (temp < 24) return "Légèrement chaud";
          return "Trop chaud";
        ]]]
      styles:
        card:
          - width: auto
          - height: auto
          - border-radius: 999px
          - border: 0
          - padding: 5px 10px 5px 10px
          - background-color: |
              [[[
                const minTemp = variables.v_min; 
                const maxTemp = variables.v_max;
                const temp = Number(entity.state) || minTemp;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100); 
                const stops = [
                  { p: 0,    c: [0, 0, 255]    },
                  { p: 25,   c: [0, 165, 255]  },
                  { p: 50,   c: [0, 255, 0]    },
                  { p: 62.5, c: [255, 255, 0]  },
                  { p: 75,   c: [255, 165, 0]  },
                  { p: 100,  c: [255, 0, 0]    }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1] || stops[0];
                const b = stops[i] || stops[stops.length - 1];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: 1.0rem
          - font-weight: 600
          - color: white
  min_temp_week:
    card:
      type: custom:button-card
      icon: mdi:arrow-down-bold
      show_name: false
      show_state: true
      layout: icon_state
      state_display: |
        [[[
          return parseFloat(states['sensor.temperature_salon_min'].state).toFixed(1) + "°";
        ]]]
      styles:
        card:
          - width: 80px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - font-size: 1.2rem
          - align-self: end
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 600
        icon:
          - width: 20px
          - color: rgba(167,176,205,1.0)
  max_temp_week:
    card:
      type: custom:button-card
      icon: mdi:arrow-up-bold
      show_name: false
      show_state: true
      layout: state_icon
      state_display: |
        [[[
          return parseFloat(states['sensor.temperature_salon_max'].state).toFixed(1) + "°";
        ]]]
      styles:
        card:
          - width: 80px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - font-size: 1.2rem
          - align-self: end
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 600
        icon:
          - width: 20px
          - color: rgba(167,176,205,1.0)
styles:
  card:
    - background-color: rgba(42,45,54,1.0)
    - aspect-ratio: 2.8/1
    - cursor: default
  custom_fields:
    icon_and_name:
      - position: absolute
      - top: 2%
      - left: 1%
    dividing_line:
      - position: absolute
      - top: 35%
      - left: 0%
    value_and_unit:
      - position: absolute
      - top: 38%
      - left: |
          [[[
            const value = Number(entity.state) || 0;
            const min = variables.v_min;
            const max = variables.v_max;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((value - min) / (max - min)) * 100, 0, 100);
            const barWidth = 360;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]
      - transform: translateX(-50%)
    bar:
      - position: absolute
      - left: 50%
      - top: 65%
      - transform: translate(-50%, -50%)
    cursor:
      - position: absolute
      - top: calc(65% - 16px)
      - left: |
          [[[
            const value = Number(entity.state) || 0;
            const min = variables.v_min;
            const max = variables.v_max;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((value - min) / (max - min)) * 100, 0, 100);
            const barWidth = 360;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]
    min_val:
      - position: absolute
      - bottom: 17%
      - left: 12%
      - width: 60px
      - display: flex
      - align-items: center
    max_val:
      - position: absolute
      - bottom: 17%
      - right: 10%
      - width: 60px
      - display: flex
      - align-items: center
      - justify-content: flex-end
    comment:
      - position: absolute
      - left: 50%
      - bottom: "-3%"
      - transform: translate(-50%, -50%)
    min_temp_week:
      - position: absolute
      - top: 40%
      - left: 5%
    max_temp_week:
      - position: absolute
      - top: 40%
      - right: 2%

Et tu trouves qu’il y a un gain ?
Parce que entre :

          - background-color: |
              [[[
                const minTemp = variables.v_min; 
                const maxTemp = variables.v_max;
                const temp = Number(entity.state) || minTemp;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100); 

et

          - background-color: |
              [[[
                const min = 14; 
                const max = 30;
                const temp = Number(entity.state) || minTemp;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100); 

Je ne suis pas sur qu’on soit au summum de l’amélioration :rofl:

Le but à la base était de répondre à la demande de @Xris :

Et il est vrai que je ne me suis pas plus que ça penché sur l’optimisation du code :wink:

Au summum non, on est ok !!

Le gain c’est que les valeurs en dur ne sont présentes qu’une seule fois au début du script ?

Ce n’est pas une critique !!!

Vu les résultat je ne me permettais pas !

L’idéal serait d’avoir un template avec lequel tu puisses avoir ton modèle unique adaptable à toutes les cartes (humidité, température, co2, pollens, IQA, etc.). Il faudra que j’y travaille :grin:

T’inquiète, je ne prends pas tes remarques pour une critique. De toute façon, avec la tête dans le guidon, tu rates forcément des choses et toute remarque constructive est bonne à prendre :wink:

En effet !

Pour ceux qui ont normalisé les noms de leurs sensors :

sensor.temperature_salon

sensor.temperature_salon_min

sensor.temperature_salon_max

il serait possible de mettre states[entity.entity_id + ‹ _min ›].state au lieu de states[‹ sensor.temperature_salon_min ›].state

Bon j’essaye d’adapter le capteur température pour l’extérieur mais je dois passer à côté d’un truc, je pense dans le calcul du positionnement du curseur et pour que les commentaires fonctionnent.

Je crois que le capteur ne remonte pas le min et le max, du coup il faudrait jouer sur l’historique ?

Je n’ai pas attaqué encore l’adaptation pollen et qualité d’air, je me dis qu’il vaut mieux y aller l’un après l’autre.

Je ne suis plus très loin :

image

type: custom:button-card
entity: sensor.netatmo_jardin_temperature
show_state: false
show_icon: false
show_name: false
tap_action: none
double_tap_action: none
hold_action: none
custom_fields:
  icon:
    card:
      type: custom:button-card
      icon: mdi:thermometer
      styles:
        card:
          - aspect-ratio: 1/1
          - width: "[[[ return window.innerWidth <= 600 ? '20px' : '25px' ]]]"
          - border: none
          - border-radius: 50%
          - background: none
        icon:
          - width: "[[[ return window.innerWidth <= 600 ? '18px' : '20px' ]]]"
          - color: white
  icon_border:
    card:
      type: custom:button-card
      styles:
        card:
          - aspect-ratio: 1/1
          - width: "[[[ return window.innerWidth <= 600 ? '23px' : '25px' ]]]"
          - border: 1px solid white
          - border-radius: 50%
          - background: none
  name:
    card:
      type: custom:button-card
      name: Netatmo Jardin Température
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: "[[[ return window.innerWidth <= 600 ? '0.9rem' : '1.0rem' ]]]"
          - align-self: start
          - justify-self: start
          - color: white
          - font-weight: 500
  bar:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - height: 6px
          - width: |
              [[[ return window.innerWidth <= 600 ? "220px" : "250px"; ]]]
          - border-radius: 999px
          - border: 0
          - padding: 0
          - background: |-
              linear-gradient(to right, rgba(0,0,255,1.0) 0%,
              rgba(0,165,255,1.0) 25%, rgba(0,255,0,1.0) 50%,
              rgba(255,255,0,1.0) 75%, rgba(255,0,0,1.0) 100%)
  cursor:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - width: 12px
          - height: 25px
          - border-radius: 999px
          - border: 4px solid rgba(42,45,54,1.0)
          - background-color: |
              [[[ 
                const minTemp = 14;
                const maxTemp = 30;
                const temp = Number(entity.state) || minTemp;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0, 0, 255, 1.0] },
                  { p: 25,c: [0, 165, 255, 1.0] },
                  { p: 50,  c: [0, 255, 0, 1.0] },
                  { p: 75,c: [255, 255, 0, 1.0] },
                  { p: 100, c: [255, 0, 0, 1.0] }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1], b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
  value:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: true
      state_display: |
        [[[ 
          const v = Number(entity.state); 
          return isNaN(v) ? '—' : v.toFixed(1); 
        ]]]
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - color: white
          - font-size: "[[[ return window.innerWidth <= 600 ? '1.6rem' : '1.8rem' ]]]"
          - font-weight: 700
  unit:
    card:
      type: custom:button-card
      name: °C
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: "[[[ return window.innerWidth <= 600 ? '1.1rem' : '1.3rem' ]]]"
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 800
  min_val:
    card:
      type: custom:button-card
      name: -20°C
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: "[[[ return window.innerWidth <= 600 ? '0.8rem' : '1.0rem' ]]]"
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  max_val:
    card:
      type: custom:button-card
      name: 60°C
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: "[[[ return window.innerWidth <= 600 ? '0.8rem' : '1.0rem' ]]]"
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const temp = Number(entity.state);
          if (temp < -5) return "Froid extrême";
          if (temp >= -5 && temp < 0) return "Très froid";
          if (temp >= 0 && temp < 10) return "Frais";
          if (temp >= 10 && temp < 20) return "Confortable";
          if (temp >= 20 && temp < 30) return "Chaud";
          if (temp >= 30 && temp < 40) return "Très chaud";
          if (temp >= 40) return "Chaleur extrême";
        ]]]
      styles:
        card:
          - height: 25px
          - width: auto
          - border-radius: 999px
          - border: none
          - padding: 0px 8px 0px 8px
          - background: white
          - background-color: |
              [[[ 
                const minTemp = -20;
                const maxTemp = 60;
                const temp = Number(entity.state);
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = isNaN(temp) ? 0 : clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0, 0, 255, 1.0] },
                  { p: 25,c: [0, 165, 255, 1.0] },
                  { p: 50,  c: [0, 255, 0, 1.0] },
                  { p: 75,c: [255, 255, 0, 1.0] },
                  { p: 100, c: [255, 0, 0, 1.0] }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1], b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: "[[[ return window.innerWidth <= 600 ? '0.8rem' : '0.9rem' ]]]"
          - font-weight: 600
          - line-height: |
              [[[ 
                return window.innerWidth <= 600 ? "0.9" : "normal";
              ]]]
          - color: |
              [[[ 
                const minTemp = -20;
                const maxTemp = 60;
                const temp = Number(entity.state);
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = isNaN(temp) ? 0 : clamp(((temp - minTemp) / (maxTemp - minTemp)) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0, 0, 255, 1.0] },
                  { p: 25,c: [0, 165, 255, 1.0] },
                  { p: 50,  c: [0, 255, 0, 1.0] },
                  { p: 75,c: [255, 255, 0, 1.0] },
                  { p: 100, c: [255, 0, 0, 1.0] }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1], b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
styles:
  card:
    - background-color: rgba(42,45,54,1.0)
    - aspect-ratio: 7/1
    - cursor: default
  custom_fields:
    icon:
      - position: absolute
      - top: 55%
      - left: 4%
      - transform: translate(-50%, -50%)
    icon_border:
      - position: absolute
      - top: "[[[ return window.innerWidth <= 600 ? '56%' : '55%' ]]]"
      - left: 4%
      - transform: translate(-50%, -50%)
    name:
      - position: absolute
      - top: "[[[ return window.innerWidth <= 600 ? '1%' : '3%' ]]]"
      - left: 8%
    value:
      - position: absolute
      - top: 0%
      - right: 6.5%
      - margin-top: "-0.5%"
    unit:
      - position: absolute
      - right: 2%
      - top: 1%
      - margin-left: 1%
    min_val:
      - position: absolute
      - bottom: 2%
      - left: "[[[ return window.innerWidth <= 600 ? '34%' : '38%' ]]]"
    max_val:
      - position: absolute
      - bottom: 2%
      - right: "[[[ return window.innerWidth <= 600 ? '2%' : '4%' ]]]"
    comment:
      - position: absolute
      - top: 55%
      - left: |
          [[[ 
            const iconLeftPercent = 1;
            const iconDiameterPx = window.innerWidth <= 600 ? 20 : 25;
            const barWidthPx = window.innerWidth <= 600 ? 220 : 250;
            const barRightPercent = window.innerWidth <= 600 ? 4 : 7;
            const iconRightExpr = `calc(${iconLeftPercent}% + ${iconDiameterPx}px)`;
            const barLeftExpr = `calc(100% - ${barRightPercent}% - ${barWidthPx}px)`;
            return `calc( ( ${iconRightExpr} + ${barLeftExpr} ) / 2 )`;
          ]]]
      - transform: translate(-50%, -50%)
    bar:
      - position: absolute
      - right: "[[[ return window.innerWidth <= 600 ? '4%' : '7%' ]]]"
      - top: 55%
      - transform: translateY(-50%)
    cursor:
      - position: absolute
      - top: "[[[ return 'calc(55% - 12.5px)'; ]]]"
      - left: |
          [[[
            const temp = Number(entity.state);
            const value = isNaN(temp) ? -20 : temp;
            const min = -20;
            const max = 60;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((value - min) / (max - min)) * 100, 0, 100);
            const barWidth = (window.innerWidth <= 600) ? 300 : 360;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]


hello,
en lecture en diagonale et vite fait du code, je vois que tu as oublié de changer ici pour le positionnement du curseur :