Refine dashboard entry points and activity views

master
Carlo Costanzo 4 days ago
parent 872a3ea2f8
commit 33a2a09eb5

@ -61,6 +61,7 @@ This folder is referenced from `config/configuration.yaml` via:
- Default Overview YAML dashboard: `lovelace.dashboards.lovelace.filename: ui-lovelace.yaml`
- Additional YAML dashboards: `filename: dashboards/<dashboard>/dashboard.yaml`
- Overview Home uses ordered production sections under `overview/sections/`; approved pilot edits now apply directly there.
- Overview Home's **Windows** ribbon opens a dedicated GPIO entry-point subview with perimeter, MQTT, and individual contact status.
- `dashboard-infrastructure` is presented as **Systems** while retaining its stable URL; it owns Home Water, Vacuum, network, compute, storage, and service drill-downs, including hidden WAN/Pi-hole/website detail views.
Note:

@ -6,7 +6,8 @@
# Systems Partial - operations summary
# House-system health strip, active issues, datacenter, and network trends.
# -------------------------------------------------------------------
# Notes: Infrastructure, Water, and Vacuum provide the operational roll-up for Systems.
# Notes: The health ribbon mirrors the visible dashboard navigation order and labels.
# Notes: DNS and external-monitoring faults roll up under Network instead of duplicating it.
# Notes: All overview trends use a 24-hour window with visible series labels.
######################################################################
@ -35,7 +36,7 @@
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: sensor.infra_dashboard_active_issue_count
name: Infrastructure
name: Systems
icon: mdi:shield-check-outline
variables:
ok_state: '0'
@ -44,30 +45,33 @@
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.infra_wan_quality_degraded
name: Network
icon: mdi:wan
entity: binary_sensor.garage_phyn_leak_alert
name: Home Water
icon: mdi:shield-water-outline
variables:
ok_state: 'off'
healthy_text: CLEAR
alert_text: LEAK
tap_action:
action: navigate
navigation_path: /dashboard-infrastructure/network
navigation_path: /dashboard-infrastructure/home-water
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.infra_dns_pihole_degraded
name: DNS
icon: mdi:dns-outline
entity: sensor.l10s_vacuum_error
name: Vacuum
icon: mdi:robot-vacuum
variables:
ok_state: 'off'
ok_state: no_error
healthy_text: READY
tap_action:
action: navigate
navigation_path: /dashboard-infrastructure/network
navigation_path: /dashboard-infrastructure/vacuum
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.infra_compute_degraded
name: Compute
name: ProxMox
icon: mdi:server-network
variables:
ok_state: 'off'
@ -77,17 +81,20 @@
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.infra_storage_degraded
name: Storage
icon: mdi:database-check-outline
entity: binary_sensor.docker_container_telemetry_degraded
name: Docker
icon: mdi:docker
variables:
ok_state: 'off'
tap_action:
action: navigate
navigation_path: /dashboard-infrastructure/docker
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.infra_external_monitoring_degraded
name: External
icon: mdi:web-check
entity: binary_sensor.infra_wan_quality_degraded
name: Network
icon: mdi:wan
variables:
ok_state: 'off'
tap_action:
@ -96,28 +103,27 @@
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.garage_phyn_leak_alert
name: Water
icon: mdi:shield-water-outline
entity: sensor.mariadb_status
name: MariaDB
icon: mdi:database
variables:
ok_state: 'off'
healthy_text: CLEAR
alert_text: LEAK
ok_state: running
healthy_text: RUNNING
tap_action:
action: navigate
navigation_path: /dashboard-infrastructure/home-water
navigation_path: /dashboard-infrastructure/mariadb
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: sensor.l10s_vacuum_error
name: Vacuum
icon: mdi:robot-vacuum
entity: sensor.bearclaw_status_telemetry
name: Joanna
icon: mdi:robot-outline
variables:
ok_state: no_error
healthy_text: READY
ok_state: ok
healthy_text: HEALTHY
tap_action:
action: navigate
navigation_path: /dashboard-infrastructure/vacuum
navigation_path: /dashboard-infrastructure/joanna
# -------------------------------------------------------------------
# Active exceptions and datacenter

@ -10,10 +10,12 @@
# Notes: Maintenance rows reuse existing reset scripts through safe more-info flows.
# Notes: Active Phyn leak alerts are shown; the integration's stale latest-test leak flag is not an operator alert.
# Notes: Daily usage uses change on the same sum-only statistic configured in Energy.
# Notes: The overview ribbon prioritizes the next maintenance action and frequent controls without hidden grid placeholders.
# Notes: Refrigerator temperature remains a temporary Home Maintenance overview item until a better permanent view is chosen.
######################################################################
# -------------------------------------------------------------------
# Water health strip (mandatory first full-width wrapper)
# Water overview ribbon (mandatory first full-width wrapper)
# -------------------------------------------------------------------
- type: grid
column_span: 4
@ -25,7 +27,7 @@
columns: full
layout_type: custom:grid-layout
layout:
grid-template-columns: repeat(6, minmax(0, 1fr))
grid-template-columns: repeat(7, minmax(0, 1fr))
grid-auto-flow: row
grid-auto-rows: min-content
grid-gap: 12px
@ -35,40 +37,109 @@
grid-template-columns: repeat(2, minmax(0, 1fr))
cards:
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: switch.phyn_autoshutoff_enabled
name: Auto Shutoff
icon: mdi:shield-water-outline
variables:
ok_state: 'on'
healthy_text: ACTIVE
alert_text: 'OFF'
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.garage_phyn_leak_alert
name: Active Leak
icon: mdi:pipe-leak
template: bearstone_infra_kpi
entity: sensor.downstairs_ac_runtime_since_last_filter_change
name: Next Maintenance
icon: mdi:calendar-clock
variables:
ok_state: 'off'
healthy_text: CLEAR
alert_text: LEAK
next_maintenance: >
[[[
const candidates = [];
const addCandidate = (entityId, label, current, limit, unit) => {
if (!Number.isFinite(current) || !Number.isFinite(limit) || limit <= 0) return;
const remaining = Math.ceil(limit - current);
candidates.push({
entity: entityId,
progress: current / limit,
text: remaining <= 0 ? `DUE · ${label}` : `${label} · ${remaining}${unit}`,
});
};
addCandidate(
'sensor.downstairs_ac_runtime_since_last_filter_change',
'DOWNSTAIRS',
Number(states['sensor.downstairs_ac_runtime_since_last_filter_change']?.state),
350,
'H',
);
addCandidate(
'sensor.upstairs_ac_runtime_since_last_filter_change',
'UPSTAIRS',
Number(states['sensor.upstairs_ac_runtime_since_last_filter_change']?.state),
450,
'H',
);
addCandidate(
'sensor.hvac_condenser_lines_days_since_cleaned',
'CONDENSER',
Number(states['sensor.hvac_condenser_lines_days_since_cleaned']?.state),
360,
'D',
);
addCandidate(
'sensor.water_softener_salt_days_since_last_add',
'SALT',
Number(states['sensor.water_softener_salt_days_since_last_add']?.state),
Number(states['sensor.water_softener_salt_average_days_between_refills']?.state),
'D',
);
candidates.sort((a, b) => b.progress - a.progress);
return candidates[0] ?? { entity: entity.entity_id, text: 'NO DATA' };
]]]
state_display: >
[[[
const text = variables?.next_maintenance?.text ?? 'NO DATA';
return text
.replace('DOWNSTAIRS', 'DOWN')
.replace('UPSTAIRS', 'UP')
.replace('CONDENSER', 'COND');
]]]
tap_action:
action: more-info
entity: >
[[[
return variables?.next_maintenance?.entity ?? entity.entity_id;
]]]
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: valve.phyn_shutoff_valve
name: Main Valve
name: Water Protection
icon: mdi:valve
variables:
ok_state: open
healthy_text: OPEN
alert_text: CLOSED
tap_action:
action: more-info
- type: custom:button-card
template: bearstone_infra_kpi
entity: sensor.rachio_controller_status
name: Sprinklers
icon: mdi:sprinkler-variant
state_display: >
[[[
const status = String(entity?.state ?? '').toLowerCase();
if (status === 'watering') {
const zones = String(entity?.attributes?.active_zones ?? '').trim();
return zones ? `RUNNING · ${zones.toUpperCase()}` : 'RUNNING';
}
if (status === 'rain_delay') return 'RAIN DELAY';
if (status === 'standby') return 'STANDBY';
if (['unknown', 'unavailable', 'none', ''].includes(status)) return 'OFFLINE';
return 'READY';
]]]
tap_action:
action: navigate
navigation_path: /dashboard-infrastructure/sprinklers
- type: custom:button-card
template: bearstone_infra_kpi
entity: sensor.phyn_average_water_flow_rate
name: Flow Rate
icon: mdi:waves-arrow-right
entity: sensor.blink_blink1_temperature
name: Refrigerator
icon: mdi:fridge-outline
- type: custom:button-card
template: bearstone_infra_kpi
@ -82,6 +153,25 @@
name: Used Today
icon: mdi:water-outline
- type: custom:button-card
template: bearstone_infra_kpi
entity: input_datetime.water_delivery_date
name: Next Delivery
icon: mdi:truck-delivery-outline
state_display: >
[[[
const raw = String(entity?.state ?? '');
const value = raw ? new Date(`${raw}T00:00:00`) : null;
if (!(value instanceof Date) || Number.isNaN(value.getTime())) return 'NO DATE';
const today = new Date();
today.setHours(0, 0, 0, 0);
const formatted = value.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }).toUpperCase();
return value < today ? `OVERDUE · ${formatted}` : formatted;
]]]
tap_action:
action: url
url_path: https://www.readyrefresh.com/en/login
# -------------------------------------------------------------------
# Home maintenance and outdoor water
# -------------------------------------------------------------------

@ -0,0 +1,354 @@
######################################################################
# @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 - Joanna Activity
# Latest 12 dispatches from BearClaw's rolling 24-hour runtime history.
# -------------------------------------------------------------------
# Notes: Rows intentionally read the dispatchActivity status attribute so the count and detail share one source of truth.
######################################################################
# -------------------------------------------------------------------
# Dispatch summary
# -------------------------------------------------------------------
- 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(4, 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(2, minmax(0, 1fr))
cards:
- type: custom:button-card
template: bearstone_infra_kpi
entity: sensor.joanna_all_dispatches_24h
name: All Jobs · 24H
icon: mdi:robot
- type: custom:button-card
template: bearstone_infra_kpi
entity: sensor.joanna_ha_dispatches_24h
name: HA Jobs · 24H
icon: mdi:home-automation
- type: custom:button-card
template: bearstone_infra_kpi
entity: sensor.joanna_queue_pending
name: Queue
icon: mdi:playlist-clock
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: sensor.joanna_ha_errors_24h
name: HA Errors · 24H
icon: mdi:alert-circle-outline
variables:
ok_state: '0'
healthy_text: NONE
raw_suffix: ERRORS
# -------------------------------------------------------------------
# Recent dispatches
# -------------------------------------------------------------------
- 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
card_mod:
style: !include /config/dashboards/infrastructure/card_mod/infra_panel.yaml
cards:
- type: custom:button-card
template: bearstone_infra_panel_header
name: Most Recent Dispatches
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 0
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No dispatches in 24 hours';
return String(item.source || 'unknown')
.replace(/^home_assistant_automation\./, 'HA · ')
.replace(/^scheduler_/, 'Scheduled · ')
.replace(/^manual_/, 'Manual · ')
.replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 1
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 2
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 3
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 4
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 5
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:vertical-stack-in-card
card_mod:
style: !include /config/dashboards/infrastructure/card_mod/infra_panel.yaml
cards:
- type: custom:button-card
template: bearstone_infra_panel_header
name: Earlier Today
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 6
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 7
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 8
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 9
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 10
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]
- type: custom:button-card
template: bearstone_infra_list_row
entity: sensor.bearclaw_status_telemetry
icon: mdi:robot-outline
variables:
activity_index: 11
name: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'No additional dispatches';
return String(item.source || 'unknown').replace(/^home_assistant_automation\./, 'HA · ').replace(/^scheduler_/, 'Scheduled · ').replace(/^manual_/, 'Manual · ').replaceAll('_', ' ');
]]]
state_display: >
[[[
const item = entity?.attributes?.dispatchActivity?.items?.[variables?.activity_index];
if (!item) return 'NO ACTIVITY';
const state = String(item.state || 'queued').replaceAll('_', ' ').toUpperCase();
const when = item.dispatchedAt ? new Date(item.dispatchedAt).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'N/A';
return `${state} · ${when}`;
]]]

@ -6,7 +6,7 @@
# Infrastructure Partial - Joanna
# Focused dispatch health, latest activity, rolling volume, and diagnostics.
# -------------------------------------------------------------------
# Notes: The large embedded logbook is replaced by a direct Activity navigation card.
# Notes: The activity drill-down reads the same rolling 24-hour runtime job history as the dispatch counters.
# Notes: This view changes HA presentation only; BearClaw runtime behavior is untouched.
######################################################################
@ -116,7 +116,7 @@
state_display: '[[[ return `${entity.state} dispatches in 24h`; ]]]'
tap_action:
action: navigate
navigation_path: /logbook?entity_id=script.joanna_dispatch
navigation_path: /dashboard-infrastructure/joanna-activity
- type: custom:vertical-stack-in-card
card_mod:

@ -0,0 +1,22 @@
######################################################################
# @CCOSTAN - Follow Me on X
# For more info visit https://www.vcloudinfo.com/click-here
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# -------------------------------------------------------------------
# Infrastructure Subview - Joanna Activity
# Latest runtime dispatches from the same 24-hour source as the counters.
# -------------------------------------------------------------------
# Notes: Hidden drill-down reached from the Joanna Dispatch Trend card.
######################################################################
title: Joanna Activity
path: joanna-activity
type: sections
subview: true
back_path: /dashboard-infrastructure/joanna
theme: default
max_columns: 4
dense_section_placement: true
badges: []
sections: !include /config/dashboards/infrastructure/partials/joanna_activity_sections.yaml
cards: []

@ -0,0 +1,290 @@
######################################################################
# @CCOSTAN - Follow Me on X
# For more info visit https://www.vcloudinfo.com/click-here
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# -------------------------------------------------------------------
# Overview Partial - GPIO entry points
# Related Issue: 1843
# Perimeter summary and all MQTT-backed entry-point contacts.
# -------------------------------------------------------------------
# Notes: Contact tiles follow group.entry_points and open more-info history.
# Notes: MQTT health is global; per-NodeMCU freshness is not currently exposed.
######################################################################
# -------------------------------------------------------------------
# Perimeter summary (mandatory first full-width wrapper)
# -------------------------------------------------------------------
- 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(4, minmax(0, 1fr))
grid-auto-flow: row
grid-auto-rows: min-content
align-items: stretch
grid-gap: 10px
margin: 0
mediaquery:
"(max-width: 900px)":
grid-template-columns: repeat(2, minmax(0, 1fr))
cards:
- type: custom:button-card
template: bearstone_infra_panel_header
name: Perimeter Summary
view_layout:
grid-column: 1 / -1
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: group.entry_points
name: GPIO Contacts
icon: mdi:window-closed-variant
variables:
ok_state: 'off'
healthy_text: SECURE
alert_text: OPEN
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mqtt_broker_problem
name: MQTT Broker
icon: mdi:message-check-outline
variables:
ok_state: 'off'
healthy_text: CONNECTED
alert_text: PROBLEM
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: lock.front_door
name: Front Lock
icon: mdi:door-closed-lock
variables:
ok_state: locked
healthy_text: LOCKED
alert_text: UNLOCKED
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: group.garage_doors
name: Garage Doors
icon: mdi:garage-variant
variables:
ok_state: closed
healthy_text: CLOSED
alert_text: OPEN
# -------------------------------------------------------------------
# Entry doors and sliders
# -------------------------------------------------------------------
- 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(4, minmax(0, 1fr))
grid-auto-flow: row
grid-auto-rows: min-content
align-items: stretch
grid-gap: 10px
margin: 0
mediaquery:
"(max-width: 900px)":
grid-template-columns: repeat(2, minmax(0, 1fr))
cards:
- type: custom:button-card
template: bearstone_infra_panel_header
name: Entry Doors and Sliders
view_layout:
grid-column: 1 / -1
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu1_gpio5
name: Front Door
icon: mdi:door-closed
variables: &contact_status
ok_state: 'off'
healthy_text: CLOSED
alert_text: OPEN
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu1_gpio12
name: Interior Garage Door
icon: mdi:door-closed
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio5
name: Back Door
icon: mdi:door-closed
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio9
name: Master Slider
icon: mdi:door-sliding
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio12
name: Main Slider
icon: mdi:door-sliding
variables: *contact_status
# -------------------------------------------------------------------
# Common-area windows
# -------------------------------------------------------------------
- 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(4, minmax(0, 1fr))
grid-auto-flow: row
grid-auto-rows: min-content
align-items: stretch
grid-gap: 10px
margin: 0
mediaquery:
"(max-width: 900px)":
grid-template-columns: repeat(2, minmax(0, 1fr))
cards:
- type: custom:button-card
template: bearstone_infra_panel_header
name: Common-Area Windows
view_layout:
grid-column: 1 / -1
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu1_gpio10
name: Dining Room Windows
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu1_gpio13
name: Front Den Windows
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu1_gpio14
name: Office Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio4
name: Dinette Windows
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio10
name: Master Bathroom Window
icon: mdi:window-closed-variant
variables: *contact_status
# -------------------------------------------------------------------
# Bedroom windows
# -------------------------------------------------------------------
- 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(4, minmax(0, 1fr))
grid-auto-flow: row
grid-auto-rows: min-content
align-items: stretch
grid-gap: 10px
margin: 0
mediaquery:
"(max-width: 900px)":
grid-template-columns: repeat(2, minmax(0, 1fr))
cards:
- type: custom:button-card
template: bearstone_infra_panel_header
name: Bedroom Windows
view_layout:
grid-column: 1 / -1
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu1_gpio4
name: Paige Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio13
name: Upstairs Bedroom Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu2_gpio14
name: Justin Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu3_gpio4
name: Stacey Bedroom Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu3_gpio5
name: Carlo Bedroom Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu3_gpio10
name: Master Bedroom Window
icon: mdi:window-closed-variant
variables: *contact_status
- type: custom:button-card
template: bearstone_infra_status_kpi
entity: binary_sensor.mcu3_gpio14
name: Upstairs Windows
icon: mdi:window-closed-variant
variables: *contact_status

@ -4,7 +4,8 @@
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# -------------------------------------------------------------------
# Overview Section - priority ribbon and daily controls
# Systems first, then frequent doors, climate, and vacuum access.
# Related Issue: 1843
# Systems first, then frequent entry points, climate, and vacuum access.
# -------------------------------------------------------------------
# Notes: Equal-width pills keep the whole ribbon compact and consistent.
######################################################################
@ -19,7 +20,7 @@ cards:
columns: full
layout_type: custom:grid-layout
layout:
grid-template-columns: repeat(6, minmax(0, 1fr))
grid-template-columns: repeat(7, minmax(0, 1fr))
grid-auto-flow: row
grid-auto-rows: min-content
align-items: center
@ -65,6 +66,21 @@ cards:
ok_states:
- locked
- type: custom:button-card
template: bearstone_overview_ribbon_control
entity: group.entry_points
name: Windows
icon: mdi:window-closed-variant
variables:
ok_states:
- 'off'
state_labels:
'off': SECURE
'on': OPEN
tap_action:
action: navigate
navigation_path: /lovelace/windows
- type: custom:button-card
template: bearstone_overview_ribbon_control
entity: climate.downstairs

@ -0,0 +1,23 @@
######################################################################
# @CCOSTAN - Follow Me on X
# For more info visit https://www.vcloudinfo.com/click-here
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# -------------------------------------------------------------------
# Overview View - GPIO entry points
# Related Issue: 1843
# Window, door, and slider contacts with perimeter and MQTT context.
# -------------------------------------------------------------------
# Notes: The Home Windows ribbon is the canonical entry point for this subview.
######################################################################
title: Windows
path: windows
subview: true
icon: mdi:window-closed-variant
theme: Backend-selected
type: sections
max_columns: 4
dense_section_placement: true
badges: []
sections: !include /config/dashboards/overview/partials/entry_points_sections.yaml
cards: []

@ -13,6 +13,7 @@
# Notes: Shared script helper `script.joanna_dispatch` lives in config/script/joanna_dispatch.yaml.
# Notes: The callback webhook writes JOANNA activity entries to logbook for traceability and optional HA alerts.
# Notes: Status telemetry polling expects !secret bearclaw_status_url (token header stays !secret bearclaw_token).
# Notes: Status telemetry includes the latest 12 dispatches in the rolling 24-hour window for the Joanna Activity drill-down.
# Notes: Codex reset-credit expiry telemetry is sourced from the appliance `codexUsage` status field.
# Notes: Codex reset walkthrough: https://youtu.be/7wKhtrvtyiI
# Notes: Codex reset companion post: https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html
@ -134,6 +135,7 @@ sensor:
value_template: "{{ 'ok' if value_json.ok | default(false) else 'error' }}"
json_attributes:
- dispatchStats
- dispatchActivity
- queue
- active
- platform

Loading…
Cancel
Save

Powered by TurnKey Linux.