###################################################################### # @CCOSTAN - Follow Me on X # For more info visit https://www.vcloudinfo.com/click-here # Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig # ------------------------------------------------------------------- # Infrastructure Partial - Website health sections # Website uptime + response windows + domain expiry telemetry view. # ------------------------------------------------------------------- # Related Issue: 1584 # Notes: Uses direct Uptime Kuma entities (no aggregate uptime min sensors). ###################################################################### # ------------------------------------------------------------------- # Website hero (mandatory first full-width container) # ------------------------------------------------------------------- - type: grid column_span: 4 columns: 1 square: false cards: - type: custom:layout-card grid_options: columns: full layout_type: custom:grid-layout layout: grid-template-columns: repeat(2, minmax(0, 1fr)) grid-auto-flow: row grid-auto-rows: min-content grid-gap: 12px margin: 0 mediaquery: "(max-width: 900px)": grid-template-columns: repeat(1, minmax(0, 1fr)) cards: - type: custom:vertical-stack-in-card grid_options: columns: full card_mod: style: !include /config/dashboards/infrastructure/card_mod/infra_panel.yaml cards: - type: custom:button-card template: bearstone_infra_panel_header name: Website Uptime - type: custom:layout-card layout_type: custom:grid-layout layout: grid-template-columns: repeat(2, minmax(0, 1fr)) grid-auto-flow: row grid-auto-rows: min-content grid-gap: 12px margin: 0 mediaquery: "(max-width: 900px)": grid-template-columns: repeat(1, minmax(0, 1fr)) cards: - type: custom:button-card template: bearstone_infra_list_row_running entity: binary_sensor.vcloudinfo_com name: vcloudinfo.com icon: mdi:web state_display: > [[[ return entity.state === 'on' ? 'UP' : (entity.state || 'unknown').toUpperCase(); ]]] - type: custom:button-card template: bearstone_infra_list_row_running entity: binary_sensor.www_kingcrafthomes_com name: kingcrafthomes.com icon: mdi:web state_display: > [[[ return entity.state === 'on' ? 'UP' : (entity.state || 'unknown').toUpperCase(); ]]] - type: custom:button-card template: bearstone_infra_list_row_running entity: binary_sensor.bear_stone name: Bear Stone icon: mdi:web-check state_display: > [[[ return entity.state === 'on' ? 'UP' : (entity.state || 'unknown').toUpperCase(); ]]] - type: custom:button-card template: bearstone_infra_list_row entity: binary_sensor.vcloudinfo_com name: vcloudinfo.com uptime icon: mdi:chart-line state_display: > [[[ const pick = (metric, window) => { const suffix = `${metric}_${window}`; const candidates = Object.keys(states).filter((k) => k.startsWith('sensor.') && k.includes('vcloudinfo_com') && k.endsWith(suffix) ); const eid = candidates[0]; return eid ? (states[eid]?.state ?? 'n/a') : 'n/a'; }; const uptime1d = pick('uptime', '1d'); const uptime30d = pick('uptime', '30d'); const uptime365d = pick('uptime', '365d'); return `1d ${uptime1d}% | 30d ${uptime30d}% | 365d ${uptime365d}%`; ]]] - type: custom:button-card template: bearstone_infra_list_row entity: binary_sensor.vcloudinfo_com name: vcloudinfo.com response icon: mdi:timer-outline state_display: > [[[ const pick = (metric, window) => { const suffix = `${metric}_${window}`; const candidates = Object.keys(states).filter((k) => k.startsWith('sensor.') && k.includes('vcloudinfo_com') && k.endsWith(suffix) ); const eid = candidates[0]; return eid ? (states[eid]?.state ?? 'n/a') : 'n/a'; }; const r1d = pick('avg_response_time', '1d'); const r30d = pick('avg_response_time', '30d'); const r365d = pick('avg_response_time', '365d'); return `1d ${r1d}s | 30d ${r30d}s | 365d ${r365d}s`; ]]] - type: custom:button-card template: bearstone_infra_list_row entity: binary_sensor.www_kingcrafthomes_com name: kingcrafthomes.com uptime icon: mdi:chart-line state_display: > [[[ const pick = (metric, window) => { const suffix = `${metric}_${window}`; const candidates = Object.keys(states).filter((k) => k.startsWith('sensor.') && (k.includes('kingcrafthomes_com') || k.includes('www_kingcrafthomes_com')) && k.endsWith(suffix) ); const eid = candidates[0]; return eid ? (states[eid]?.state ?? 'n/a') : 'n/a'; }; const uptime1d = pick('uptime', '1d'); const uptime30d = pick('uptime', '30d'); const uptime365d = pick('uptime', '365d'); return `1d ${uptime1d}% | 30d ${uptime30d}% | 365d ${uptime365d}%`; ]]] - type: custom:button-card template: bearstone_infra_list_row entity: binary_sensor.www_kingcrafthomes_com name: kingcrafthomes.com response icon: mdi:timer-outline state_display: > [[[ const pick = (metric, window) => { const suffix = `${metric}_${window}`; const candidates = Object.keys(states).filter((k) => k.startsWith('sensor.') && (k.includes('kingcrafthomes_com') || k.includes('www_kingcrafthomes_com')) && k.endsWith(suffix) ); const eid = candidates[0]; return eid ? (states[eid]?.state ?? 'n/a') : 'n/a'; }; const r1d = pick('avg_response_time', '1d'); const r30d = pick('avg_response_time', '30d'); const r365d = pick('avg_response_time', '365d'); return `1d ${r1d}s | 30d ${r30d}s | 365d ${r365d}s`; ]]] - type: custom:vertical-stack-in-card grid_options: columns: full card_mod: style: !include /config/dashboards/infrastructure/card_mod/infra_panel.yaml cards: - type: custom:button-card template: bearstone_infra_panel_header name: Domain Expiry - type: custom:layout-card layout_type: custom:grid-layout layout: grid-template-columns: repeat(2, minmax(0, 1fr)) grid-auto-flow: row grid-auto-rows: min-content grid-gap: 12px margin: 0 mediaquery: "(max-width: 900px)": grid-template-columns: repeat(1, minmax(0, 1fr)) cards: - type: custom:button-card template: bearstone_infra_list_row entity: sensor.vcloudinfo_com_days_until_expiration name: vcloudinfo.com icon: mdi:calendar-clock state_display: > [[[ const days = states['sensor.vcloudinfo_com_days_until_expiration']?.state ?? 'n/a'; const expRaw = states['sensor.vcloudinfo_com_expires']?.state; let exp = 'n/a'; const s = String(expRaw ?? ''); if (s && !['unknown','unavailable','none',''].includes(s.toLowerCase())) { if (/^\d{4}-\d{2}-\d{2}/.test(s)) { exp = s.slice(0, 10); } else { const dt = new Date(s); if (!Number.isNaN(dt.getTime())) { const y = dt.getFullYear(); const m = String(dt.getMonth() + 1).padStart(2, '0'); const d = String(dt.getDate()).padStart(2, '0'); exp = `${y}-${m}-${d}`; } } } return `${days}d | ${exp}`; ]]] - type: custom:button-card template: bearstone_infra_list_row entity: sensor.kingcrafthomes_com_days_until_expiration name: kingcrafthomes.com icon: mdi:calendar-clock state_display: > [[[ const days = states['sensor.kingcrafthomes_com_days_until_expiration']?.state ?? 'n/a'; const expRaw = states['sensor.kingcrafthomes_com_expires']?.state; let exp = 'n/a'; const s = String(expRaw ?? ''); if (s && !['unknown','unavailable','none',''].includes(s.toLowerCase())) { if (/^\d{4}-\d{2}-\d{2}/.test(s)) { exp = s.slice(0, 10); } else { const dt = new Date(s); if (!Number.isNaN(dt.getTime())) { const y = dt.getFullYear(); const m = String(dt.getMonth() + 1).padStart(2, '0'); const d = String(dt.getDate()).padStart(2, '0'); exp = `${y}-${m}-${d}`; } } } return `${days}d | ${exp}`; ]]] - type: grid column_span: 4 columns: 3 square: false cards: - type: custom:button-card template: bearstone_infra_alert_row entity: binary_sensor.infra_website_degraded name: Website status degraded icon: mdi:web-off variables: alert_kind: binary_on - type: custom:button-card template: bearstone_infra_alert_row entity: binary_sensor.infra_website_uptime_slo_breach name: Uptime SLO breach icon: mdi:alert-decagram variables: alert_kind: binary_on - type: custom:button-card template: bearstone_infra_alert_row entity: binary_sensor.infra_website_latency_degraded name: Website latency degraded icon: mdi:timer-alert variables: alert_kind: binary_on