title: Доступность устройств
views:
- title: Доступность устройств
path: availability
cards:
# ═══ Переключатель периода ═══
- type: entities
entities:
- entity: input_select.avail_period
name: Период
style:
card:
padding: 8px 16px
# ═══ Кнопка обновить + статус ═══
- type: entities
entities:
- entity: sensor.avail_calc_progress
name: Статус
- entity: input_select.avail_period
name: Период (для обновления)
# ═══ Сводная карточка ═══
- type: custom:button-card
entity: sensor.avail_calc_progress
show_name: false
show_state: false
show_icon: false
custom_fields:
card: |
[[[
const devs = Object.entries(hass.states)
.filter(([k]) => k.startsWith('sensor.avail_') && !k.startsWith('sensor.avail_area_') && !k.startsWith('sensor.avail_calc_'))
.map(([k,v]) => ({ id: k, pct: parseFloat(v.state), attrs: v.attributes }));
if (!devs.length) return '
`;
h += `
Средняя доступность
`;
h += `
`;
h += `
`;
h += `
${avg}%
`;
h += `
`;
if (problems.length) {
h += `
🔴 Проблемных (<95%): ${problems.length}
`;
problems.slice(0, 5).forEach(p => {
const ic = {switch:'🔌',light:'💡',binary_sensor:'️',sensor:'️',climate:'️',cover:'',lock:'🔒',media_player:'🔊',device_tracker:'📍',vacuum:'🤖',fan:'🌀',humidifier:'💨',water_heater:'🚿',siren:'🚨',button:'🔘'}[p.attrs.entity_id?.split('.')[0]] || '📡';
const pc = p.pct < 90 ? 'var(--error-color)' : 'var(--warning-color)';
const ti = p.attrs.trend === 'down' ? '📉' : p.attrs.trend === 'up' ? '📈' : '➡️';
h += `
`;
h += `${ic}${p.attrs.friendly_name || p.id.split('.')[1].replace(/_/g,' ')}`;
h += `${p.pct}%${ti}`;
h += `
`;
});
}
h += `
`;
h += `📉 Хуже: ${worse}📈 Лучше: ${better}`;
h += `
`;
h += `
`;
return h;
]]]
styles:
card:
- padding: 0
- background: var(--card-background-color)
# ═══ Список всех устройств (автоматический) ═══
- type: custom:auto-entities
card:
type: entities
title: Устройства
filter:
include:
- entity_id: "sensor.avail_*"
exclude:
- entity_id: "sensor.avail_area_*"
- entity_id: "sensor.avail_calc_*"
sort:
method: state
numeric: true
reverse: true
card_mod:
style: |
ha-card {
margin-top: 8px;
}
ha-card .entity-row {
display: grid;
grid-template-columns: 40px 1fr 80px 40px;
align-items: center;
gap: 8px;
}
@media (max-width: 600px) {
ha-card .entity-row {
grid-template-columns: 30px 1fr 60px;
}
ha-card .entity-row .state {
display: none;
}
}