Salut à tous,
J'ai fait une carte pour afficher l'état du soleil avec le prochain lever/coucher du soleil et dans combien de temps. Une barre d'avance est incluse avec une icône de soleil/lune suivant l'état du soleil. Le badge est pour afficher les UV du soleil en journée et sera caché la nuit.
L'entité utilisée pour l'UV est celle fournie par l'intégration Météo France, penser à remplacer le nom de l'entité.
Installer button-card depuis HACS.
les icônes animées, à placer dans /config/www/weather/animated ou sous file editor, c'est /homeassistant/www/weather/animated.
Code
type: custom:button-card
entity: sun.sun
update_timer: 10s
show_icon: false
show_name: true
show_label: true
show_state: false
show_entity_picture: true
tap_action:
action: more-info
hold_action:
action: more-info
entity: sensor.xxxx_uv
entity_picture: |
[[[
return entity.state == "below_horizon"
? "/local/weather/animated/night.svg"
: "/local/weather/animated/day.svg";
]]]
name: |
[[[
const sunrise = new Date(states["sensor.sun_next_rising"].state);
const sunset = new Date(states["sensor.sun_next_setting"].state);
function heure(d){
return d.toLocaleTimeString("fr-FR",
{hour:"2-digit",minute:"2-digit"}).replace(":","h");
}
if (sunrise < sunset)
return `Soleil sous l'horizon | Prochain lever: ${heure(sunrise)}`;
return `Soleil au-dessus de l'horizon | Prochain coucher: ${heure(sunset)}`;
]]]
label: |
[[[
const sunrise = new Date(states["sensor.sun_next_rising"].state);
const sunset = new Date(states["sensor.sun_next_setting"].state);
const next = sunrise < sunset ? sunrise : sunset;
let sec = Math.floor((next - new Date()) / 1000);
if (sec <= 0)
return "Maintenant";
const d = Math.floor(sec / 86400);
sec %= 86400;
const h = Math.floor(sec / 3600);
sec %= 3600;
const m = Math.floor(sec / 60);
const s = sec % 60;
let txt = "Dans ";
if (d > 0) txt += `${d}j `;
if (h > 0) {
txt += `${String(h).padStart(2,"0")}h`;
txt += `${String(m).padStart(2,"0")}m`;
} else if (m > 0) {
txt += `${m}m`;
}
txt += `${String(s).padStart(2,"0")}s`;
return txt;
]]]
custom_fields:
uv: |
[[[
if (entity.state == "below_horizon") return "";
return states["sensor.xxxx_uv"].state;
]]]
progress: |
[[[
const sunrise = new Date(states['sensor.sun_next_rising'].state);
const sunset = new Date(states['sensor.sun_next_setting'].state);
const now = new Date();
let start, end, icon, gradient, offset;
if (sunrise < sunset) {
// Nuit
end = sunrise;
start = new Date(sunrise);
start.setDate(start.getDate()-1);
icon = "🌙";
offset = 17;
gradient = "linear-gradient(90deg,#435CFF,#5C6BC0,#FFF59D)";
} else {
// Jour
start = new Date(sunset);
start.setDate(start.getDate()-1);
end = sunset;
icon = "☀️";
offset = 12;
gradient = "linear-gradient(90deg,#FFE082,#FFB300,#F57C00)";
}
let pct = ((now - start) / (end - start)) * 100;
pct = Math.max(0, Math.min(100, pct));
const iconPct = Math.max(2, Math.min(98, pct));
return `
<div style="
position:relative;
width:100%;
height:8px;
border-radius:999px;
background:rgba(255,255,255,.18);
overflow:visible;">
<div style="
width:${pct}%;
height:100%;
border-radius:999px;
background:${gradient};">
</div>
<div style="
position:absolute;
left: calc(${iconPct}% - ${offset}px);
top:20%;
transform:translateY(-55%);
font-size:19px;
transition:left 1s linear;">
${icon}
</div>
</div>`;
]]]
styles:
card:
- height: 58px
- padding: 3px 0px
- border-radius: 12px
- overflow: visible
- overflow: hidden
- background: |
[[[
return entity.state=="below_horizon"
? "linear-gradient(180deg,#40445a 0%, rgba(64,68,90,.15) 250%)"
: "linear-gradient(180deg,#44739e 0%, rgba(68,115,158,.15) 250%)";
]]]
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
- "--button-card-ripple-color": |
[[[
return entity.state=="below_horizon"
? "#f9e491"
: "#ffe54d";
]]]
grid:
- grid-template-areas: |
"i n"
"i l "
"i progress"
- grid-template-columns: 54px 1fr
- grid-template-rows: min-content min-content 7px
img_cell:
- width: 54px
- height: 54px
- justify-content: center
- align-items: center
icon:
- width: 80px
- height: 80px
name:
- align-self: end
- justify-self: start
- font-size: 16px
- font-weight: 500
- color: white
label:
- justify-self: start
- align-self: start
- font-size: 15px
- font-weight: bold
- padding-bottom: 8px
- color: |
[[[
return entity.state=="below_horizon"
? "#f9e491"
: "#ffe54d";
]]]
custom_fields:
progress:
- justify-self: stretch
- align-self: center
- overflow: visible
- width: calc(100% - 10px)
- padding-bottom: 12px
- filter: drop-shadow(0 1px 2px rgba(0,0,0,.35))
uv:
- position: absolute
- top: 3px
- left: 34px
- width: 16px
- height: 16px
- border-radius: 50%
- display: |
[[[
return entity.state == "below_horizon"
? "none"
: "flex";
]]]
- justify-content: center
- align-items: center
- font-size: 11px
- font-weight: bold
- color: white
- z-index: 10
- box-shadow: 0 2px 5px rgba(0,0,0,.35)
- background-color: |
[[[
const uv = Number(states['sensor.xxxx_uv'].state);
if (uv >= 11) return "purple";
if (uv >= 8) return "firebrick";
if (uv >= 6) return "darkorange";
if (uv >= 3) return "gold";
return "forestgreen";
]]]
Vous avez la base, changez si besoin les couleurs à votre guise.
Bonne journée.







