-
-
Save hectorzin/eaf4f74b2ab5fc1b3858136c561aa0d8 to your computer and use it in GitHub Desktop.
Panel calidad del aire
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type: vertical-stack | |
| cards: | |
| - type: custom:button-card | |
| name: Calidad del aire exterior | |
| entity: sensor.o_1pst_temperatura | |
| double_tap_action: | |
| action: more-info | |
| entity: sensor.o_1pst_humedad | |
| show_state: true | |
| show_icon: false | |
| custom_fields: | |
| pill_t: | | |
| [[[ | |
| const t = Number(states['sensor.o_1pst_temperatura']?.state) || 0; | |
| return (t.toFixed(1) + ' °C'); | |
| ]]] | |
| pill_h: | | |
| [[[ | |
| const h = Number(states['sensor.o_1pst_humedad']?.state) || 0; | |
| return (h.toFixed(0) + ' %'); | |
| ]]] | |
| styles: | |
| grid: | |
| - grid-template-areas: "\"n pill_t pill_h\" \"s pill_t pill_h\"" | |
| - grid-template-columns: 1fr auto auto | |
| - grid-template-rows: auto auto | |
| - column-gap: 8px | |
| - row-gap: 2px | |
| card: | |
| - padding: 16px | |
| - border-radius: 18px | |
| - box-shadow: none | |
| - color: black | |
| - background: | | |
| [[[ | |
| const co2 = Number(states['sensor.o_1pst_dioxido_de_carbono']?.state) || 0; | |
| const pm25 = Number(states['sensor.o_1pst_pm2_5']?.state) || 0; | |
| const pm10 = Number(states['sensor.o_1pst_pm10']?.state) || 0; | |
| const voc = Number(states['sensor.o_1pst_indice_cov']?.state) || 0; | |
| const nox = Number(states['sensor.o_1pst_indice_nox']?.state) || 0; | |
| const sevCo2 = v => v<=800?0 : v<=1000?1 : v<=1400?2 : v<=2000?3 : 4; | |
| const sevPM25 = v => v<=10?0 : v<=15?1 : v<=25?2 : v<=35?3 : v<=55?4 : 5; | |
| const sevPM10 = v => v<=20?0 : v<=45?2 : v<=90?3 : 4; | |
| const sevVOC = v => v<=100?0 : v<=200?2 : v<=300?3 : 4; | |
| const sevNOx = v => v<=50?0 : v<=100?2 : v<=200?3 : 4; | |
| const worst = Math.max(sevCo2(co2), sevPM25(pm25), sevPM10(pm10), sevVOC(voc), sevNOx(nox)); | |
| const colors = [ | |
| 'linear-gradient(135deg,#00C853,#2ECC71)', // verde vivo | |
| 'linear-gradient(135deg,#C6FF00,#AEEA00)', // lima brillante | |
| 'linear-gradient(135deg,#FFEB3B,#FDD835)', // amarillo | |
| 'linear-gradient(135deg,#FFA726,#FB8C00)', // naranja | |
| 'linear-gradient(135deg,#FF5252,#E53935)', // rojo | |
| 'linear-gradient(135deg,#BA68C8,#8E24AA)' // morado (PM2.5 muy alto) | |
| ]; | |
| return colors[Math.min(worst,5)]; | |
| ]]] | |
| name: | |
| - font-size: 18px | |
| - font-weight: 700 | |
| state: | |
| - font-size: 14px | |
| - opacity: 0.9 | |
| custom_fields: | |
| pill_t: | |
| - align-self: center | |
| - justify-self: end | |
| - padding: 6px 10px | |
| - border-radius: 999px | |
| - font-weight: 700 | |
| - color: black | |
| - background: | | |
| [[[ | |
| const t = Number(states['sensor.o_1pst_temperatura']?.state) || 0; | |
| if (t<10) return 'linear-gradient(135deg,#90CAF9,#64B5F6)'; // frío (azules vivos, claros) | |
| if (t<18) return 'linear-gradient(135deg,#64B5F6,#42A5F5)'; | |
| if (t<=24) return 'linear-gradient(135deg,#00C853,#2ECC71)'; // templado (verde) | |
| if (t<=28) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; // cálido | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; // calor | |
| ]]] | |
| pill_h: | |
| - align-self: center | |
| - justify-self: end | |
| - padding: 6px 10px | |
| - border-radius: 999px | |
| - font-weight: 700 | |
| - color: black | |
| - background: | | |
| [[[ | |
| const h = Number(states['sensor.o_1pst_humedad']?.state) || 0; | |
| if (h<30) return 'linear-gradient(135deg,#FFB74D,#FF9800)'; // seco | |
| if (h<40) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; // seco-aceptable | |
| if (h<=60) return 'linear-gradient(135deg,#00C853,#2ECC71)'; // confortable | |
| if (h<=80) return 'linear-gradient(135deg,#90CAF9,#64B5F6)'; // húmedo | |
| return 'linear-gradient(135deg,#64B5F6,#42A5F5)'; // muy húmedo (azules vivos) | |
| ]]] | |
| state_display: | | |
| [[[ | |
| const co2 = Number(states['sensor.o_1pst_dioxido_de_carbono']?.state) || 0; | |
| const pm25 = Number(states['sensor.o_1pst_pm2_5']?.state) || 0; | |
| const pm10 = Number(states['sensor.o_1pst_pm10']?.state) || 0; | |
| const voc = Number(states['sensor.o_1pst_indice_cov']?.state) || 0; | |
| const nox = Number(states['sensor.o_1pst_indice_nox']?.state) || 0; | |
| const label = v => ['Bueno','Aceptable','Moderado','Regular','Malo','Muy malo'][v]; | |
| const sevCo2 = v => v<=800?0 : v<=1000?1 : v<=1400?2 : v<=2000?3 : 4; | |
| const sevPM25 = v => v<=10?0 : v<=15?1 : v<=25?2 : v<=35?3 : v<=55?4 : 5; | |
| const sevPM10 = v => v<=20?0 : v<=45?2 : v<=90?3 : 4; | |
| const sevVOC = v => v<=100?0 : v<=200?2 : v<=300?3 : 4; | |
| const sevNOx = v => v<=50?0 : v<=100?2 : v<=200?3 : 4; | |
| const worst = Math.max(sevCo2(co2), sevPM25(pm25), sevPM10(pm10), sevVOC(voc), sevNOx(nox)); | |
| return label(worst); | |
| ]]] | |
| - type: grid | |
| columns: 2 | |
| square: false | |
| cards: | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_pm2_5 | |
| name: PM2.5 (µg/m³) | |
| icon: mdi:blur | |
| show_state: true | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(1)+' µg/m³'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=10) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=15) return 'linear-gradient(135deg,#C6FF00,#AEEA00)'; | |
| if (v<=25) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=35) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| if (v<=55) return 'linear-gradient(135deg,#FF9800,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_pm10 | |
| name: PM10 (µg/m³) | |
| icon: mdi:blur-linear | |
| show_state: true | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(0)+' µg/m³'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=20) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=45) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=90) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_dioxido_de_carbono | |
| name: CO₂ (ppm) | |
| icon: mdi:molecule-co2 | |
| show_state: true | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(0)+' ppm'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=800) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=1000) return 'linear-gradient(135deg,#C6FF00,#AEEA00)'; | |
| if (v<=1400) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=2000) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_indice_cov | |
| name: COV — índice | |
| icon: mdi:chemical-weapon | |
| show_state: true | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=100) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=200) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=300) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_indice_nox | |
| name: NOx — índice | |
| icon: mdi:tailwind | |
| show_state: true | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=50) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=100) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=200) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_pm1 | |
| name: PM1 (µg/m³) | |
| icon: mdi:blur-radial | |
| show_state: true | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(1)+' µg/m³'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=10) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=25) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=35) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type: vertical-stack | |
| cards: | |
| - type: horizontal-stack | |
| cards: | |
| - type: custom:button-card | |
| name: Calidad del aire exterior | |
| entity: sensor.o_1pst_pm2_5 | |
| tap_action: | |
| action: more-info | |
| show_state: true | |
| show_icon: false | |
| styles: | |
| card: | |
| - height: 56px | |
| - padding: 12px 16px | |
| - border-radius: 18px | |
| - box-shadow: none | |
| - color: black | |
| - background: | | |
| [[[ | |
| const co2 = Number(states['sensor.o_1pst_dioxido_de_carbono']?.state)||0; | |
| const pm25 = Number(states['sensor.o_1pst_pm2_5']?.state)||0; | |
| const pm10 = Number(states['sensor.o_1pst_pm10']?.state)||0; | |
| const voc = Number(states['sensor.o_1pst_indice_cov']?.state)||0; | |
| const nox = Number(states['sensor.o_1pst_indice_nox']?.state)||0; | |
| const sevCo2 = v => v<=800?0 : v<=1000?1 : v<=1400?2 : v<=2000?3 : 4; | |
| const sevPM25 = v => v<=10?0 : v<=15?1 : v<=25?2 : v<=35?3 : v<=55?4 : 5; | |
| const sevPM10 = v => v<=20?0 : v<=45?2 : v<=90?3 : 4; | |
| const sevVOC = v => v<=100?0 : v<=200?2 : v<=300?3 : 4; | |
| const sevNOx = v => v<=50?0 : v<=100?2 : v<=200?3 : 4; | |
| const worst = Math.max(sevCo2(co2), sevPM25(pm25), sevPM10(pm10), sevVOC(voc), sevNOx(nox)); | |
| const colors = [ | |
| 'linear-gradient(135deg,#00C853,#2ECC71)', | |
| 'linear-gradient(135deg,#C6FF00,#AEEA00)', | |
| 'linear-gradient(135deg,#FFEB3B,#FDD835)', | |
| 'linear-gradient(135deg,#FFA726,#FB8C00)', | |
| 'linear-gradient(135deg,#FF5252,#E53935)', | |
| 'linear-gradient(135deg,#BA68C8,#8E24AA)' | |
| ]; | |
| return colors[Math.min(worst,5)]; | |
| ]]] | |
| name: | |
| - font-size: 18px | |
| - font-weight: 700 | |
| state: | |
| - font-size: 14px | |
| - opacity: 0.9 | |
| state_display: | | |
| [[[ | |
| const co2 = Number(states['sensor.o_1pst_dioxido_de_carbono']?.state)||0; | |
| const pm25 = Number(states['sensor.o_1pst_pm2_5']?.state)||0; | |
| const pm10 = Number(states['sensor.o_1pst_pm10']?.state)||0; | |
| const voc = Number(states['sensor.o_1pst_indice_cov']?.state)||0; | |
| const nox = Number(states['sensor.o_1pst_indice_nox']?.state)||0; | |
| const label = v => ['Bueno','Aceptable','Moderado','Regular','Malo','Muy malo'][v]; | |
| const sevCo2 = v => v<=800?0 : v<=1000?1 : v<=1400?2 : v<=2000?3 : 4; | |
| const sevPM25 = v => v<=10?0 : v<=15?1 : v<=25?2 : v<=35?3 : v<=55?4 : 5; | |
| const sevPM10 = v => v<=20?0 : v<=45?2 : v<=90?3 : 4; | |
| const sevVOC = v => v<=100?0 : v<=200?2 : v<=300?3 : 4; | |
| const sevNOx = v => v<=50?0 : v<=100?2 : v<=200?3 : 4; | |
| const worst = Math.max(sevCo2(co2), sevPM25(pm25), sevPM10(pm10), sevVOC(voc), sevNOx(nox)); | |
| return label(worst); | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_temperatura | |
| tap_action: | |
| action: more-info | |
| show_name: false | |
| show_icon: false | |
| show_state: true | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; return v.toFixed(1)+' °C'; | |
| ]]] | |
| styles: | |
| card: | |
| - width: 92px | |
| - height: 56px | |
| - margin: 0 0 0 8px | |
| - border-radius: 999px | |
| - box-shadow: none | |
| - color: black | |
| - font-weight: 700 | |
| - background: | | |
| [[[ | |
| const t = Number(entity.state)||0; | |
| if (t<10) return 'linear-gradient(135deg,#90CAF9,#64B5F6)'; | |
| if (t<18) return 'linear-gradient(135deg,#64B5F6,#42A5F5)'; | |
| if (t<=24) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (t<=28) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_humedad | |
| tap_action: | |
| action: more-info | |
| show_name: false | |
| show_icon: false | |
| show_state: true | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; return v.toFixed(0)+' %'; | |
| ]]] | |
| styles: | |
| card: | |
| - width: 92px | |
| - height: 56px | |
| - margin: 0 0 0 8px | |
| - border-radius: 999px | |
| - box-shadow: none | |
| - color: black | |
| - font-weight: 700 | |
| - background: | | |
| [[[ | |
| const h = Number(entity.state)||0; | |
| if (h<30) return 'linear-gradient(135deg,#FFB74D,#FF9800)'; | |
| if (h<40) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (h<=60) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (h<=80) return 'linear-gradient(135deg,#90CAF9,#64B5F6)'; | |
| return 'linear-gradient(135deg,#64B5F6,#42A5F5)'; | |
| ]]] | |
| - type: grid | |
| columns: 2 | |
| square: false | |
| cards: | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_pm2_5 | |
| name: PM2.5 (µg/m³) | |
| icon: mdi:blur | |
| show_state: true | |
| tap_action: | |
| action: more-info | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(1)+' µg/m³'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=10) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=15) return 'linear-gradient(135deg,#C6FF00,#AEEA00)'; | |
| if (v<=25) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=35) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| if (v<=55) return 'linear-gradient(135deg,#FF9800,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_pm10 | |
| name: PM10 (µg/m³) | |
| icon: mdi:blur-linear | |
| show_state: true | |
| tap_action: | |
| action: more-info | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(0)+' µg/m³'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=20) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=45) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=90) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_dioxido_de_carbono | |
| name: CO₂ (ppm) | |
| icon: mdi:molecule-co2 | |
| show_state: true | |
| tap_action: | |
| action: more-info | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(0)+' ppm'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=800) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=1000) return 'linear-gradient(135deg,#C6FF00,#AEEA00)'; | |
| if (v<=1400) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=2000) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_indice_cov | |
| name: COV — índice | |
| icon: mdi:chemical-weapon | |
| show_state: true | |
| tap_action: | |
| action: more-info | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=100) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=200) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=300) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_indice_nox | |
| name: NOx — índice | |
| icon: mdi:tailwind | |
| show_state: true | |
| tap_action: | |
| action: more-info | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=50) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=100) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=200) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] | |
| - type: custom:button-card | |
| entity: sensor.o_1pst_pm1 | |
| name: PM1 (µg/m³) | |
| icon: mdi:blur-radial | |
| show_state: true | |
| tap_action: | |
| action: more-info | |
| state_display: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| return v.toFixed(1)+' µg/m³'; | |
| ]]] | |
| styles: | |
| card: | |
| - border-radius: 16px | |
| - box-shadow: none | |
| - color: black | |
| - padding: 14px | |
| - background: | | |
| [[[ | |
| const v = Number(entity.state)||0; | |
| if (v<=10) return 'linear-gradient(135deg,#00C853,#2ECC71)'; | |
| if (v<=25) return 'linear-gradient(135deg,#FFEB3B,#FDD835)'; | |
| if (v<=35) return 'linear-gradient(135deg,#FFA726,#FB8C00)'; | |
| return 'linear-gradient(135deg,#FF5252,#E53935)'; | |
| ]]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment