Test de transposition rapide via copilot depuis le dernier code de température vers celui pour le dioxyde de carbone, j’ai l’impression que c’est bon, je vais voir pour réduire un peu l’espace entre la value et unit je pense:
type: custom:button-card
entity: sensor.netatmo_salon_dioxyde_de_carbone
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:molecule-co2
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 Salon dioxyde de carbone
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,255,24,1.0) 0%,
rgba(152,255,0,1.0) 40%,
rgba(255,252,0,1.0) 55%,
rgba(255,174,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 min = 400;
const max = 2000;
const ppm = Number(entity.state);
const safe = isNaN(ppm) ? min : ppm;
const clamp = (v, mn, mx) => Math.max(mn, Math.min(mx, v));
const percent = clamp(((safe - min) / (max - min)) * 100, 0, 100);
const stops = [
{ p: 0, c: [0, 255, 24] },
{ p: 40, c: [152, 255, 0] },
{ p: 55, c: [255, 252, 0] },
{ p: 75, c: [255, 174, 0] },
{ p: 100, c: [255, 0, 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(0);
]]]
styles:
card:
- width: auto
- padding: 0
- border: none
- border-radius: 0
- background: none
state:
- color: white
- font-size: "[[[ return window.innerWidth <= 600 ? '1.4rem' : '1.8rem' ]]]"
- font-weight: 700
unit:
card:
type: custom:button-card
name: ppm
styles:
card:
- width: auto
- padding: 0
- border: none
- border-radius: 0
- background: none
name:
- font-size: "[[[ return window.innerWidth <= 600 ? '1.0rem' : '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: "400"
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: "2000"
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 ppm = Number(entity.state);
if (isNaN(ppm)) return "Indisponible";
if (ppm < 900) return "Excellent";
if (ppm >= 900 && ppm <= 1150) return "Bon";
if (ppm >= 1151 && ppm <= 1400) return "Acceptable";
if (ppm >= 1401 && ppm <= 1600) return "Mauvais";
if (ppm > 1600) return window.innerWidth <= 600 ? "Malsain" : "Malsain";
return "Indisponible";
]]]
styles:
card:
- height: 25px
- width: auto
- border-radius: 999px
- border: none
- padding: 0px 8px 0px 8px
- background: white
- background-color: |
[[[
const min = 400;
const max = 2000;
const ppm = Number(entity.state);
const clamp = (v, mn, mx) => Math.max(mn, Math.min(mx, v));
const percent = isNaN(ppm) ? 0 : clamp(((ppm - min) / (max - min)) * 100, 0, 100);
const stops = [
{ p: 0, c: [0, 255, 24] },
{ p: 40, c: [152, 255, 0] },
{ p: 55, c: [255, 252, 0] },
{ p: 75, c: [255, 174, 0] },
{ p: 100, c: [255, 0, 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 ppm = Number(entity.state) || 0;
if (ppm < 900) return "rgba(0,255,24,1.0)";
if (ppm >= 900 && ppm <= 1150) return "rgba(152,255,0,1.0)";
if (ppm >= 1151 && ppm <= 1400) return "rgba(255,252,0,1.0)";
if (ppm >= 1401 && ppm <= 1600) return "rgba(255,174,0,1.0)";
if (ppm > 1600) return "rgba(255,113,0,1.0)";
return "rgba(167,176,205,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: "[[[ return window.innerWidth <= 600 ? '2%' : '1%' ]]]"
- right: "[[[ return window.innerWidth <= 600 ? '12%' : '10%' ]]]"
unit:
- position: absolute
- right: "[[[ return window.innerWidth <= 600 ? '3%' : '2%' ]]]"
- top: "[[[ return window.innerWidth <= 600 ? '2%' : '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 min = 400;
const max = 2000;
const value = Number(entity.state);
const clamp = (v, mn, mx) => Math.max(mn, Math.min(mx, v));
const t = clamp(value, min, max);
const barWidth = window.innerWidth <= 600 ? 220 : 250;
const halfCursor = 8;
const barRightPercent = window.innerWidth <= 600 ? 4 : 7;
const percent = ((t - min) / (max - min)) * 100;
const offsetPx = (barWidth * percent) / 100;
return `calc(100% - ${barRightPercent}% - ${barWidth}px + ${offsetPx}px - ${halfCursor}px)`;
]]]









