You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
946 lines
42 KiB
946 lines
42 KiB
######################################################################
|
|
# @CCOSTAN - Follow Me on X
|
|
# For more info visit https://www.vcloudinfo.com/click-here
|
|
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
|
|
# -------------------------------------------------------------------
|
|
# Kiosk Tablets - Fully recovery and Kiosk Satellite display policy
|
|
# Keeps the Bedroom tablet stable and drives state-based Kitchen Show camera views.
|
|
# -------------------------------------------------------------------
|
|
# Related Issue: 1875
|
|
# Related Issue: 1890
|
|
# Related Issue: 1895
|
|
# Notes: `/dashboard-bedroom/home` remains the canonical desktop/future-hardware route.
|
|
# Notes: The Android 5 Fully tablet uses `/local/bedroom-kiosk.html`, a lightweight renderer.
|
|
# Notes: Shared camera, header, and alert sensors keep both Bedroom renderers DRY.
|
|
# Notes: Fully controls apply only to the legacy Bedroom tablet.
|
|
# Notes: Kitchen Show uses Kiosk Satellite's native ESPHome entities; `_2` is the live set while legacy MQTT registry entries coexist.
|
|
# Notes: Kiosk Satellite owns HA kiosk-mode hiding, connection recovery, HA camera import, and HLS-first playback; no kiosk-mode custom resource is loaded.
|
|
# Notes: Kitchen Show uses the Dim screensaver while empty/asleep; true panel-off is disabled because this Crown build naps Wi-Fi and cannot accept a remote wake.
|
|
# Notes: Kitchen Show volume is corrected to 13% at 08:00 and after HA or kiosk startup; manual changes otherwise persist.
|
|
# Notes: Garage takes over while either door is moving/open and remains for three minutes after both close; Front Door takes over while unlocked.
|
|
# Notes: At 07:00, Home Assistant stages a pending Kiosk Satellite release, then dispatches Joanna daily until installation is verified.
|
|
# Notes: Wake events only restore brightness/focus; URL reloads require page drift.
|
|
# Notes: Fully auto-reload on screen-on/screensaver-stop is disabled to avoid motion wake reload loops.
|
|
# Notes: Startup recovery waits for HA's initial websocket state burst to settle.
|
|
# Notes: Brightness recovery only runs when both SleepIQ in-bed sensors are off.
|
|
# Notes: Fully availability/page/app/power plus Kitchen connectivity, current-page/screenshot freshness, and update state feed Systems telemetry.
|
|
# Notes: Kitchen updates are advisory telemetry and do not raise kiosk or Systems fault rollups.
|
|
# Notes: Kiosk attention sensors expose only their stable status attribute so recorder preserves problem transitions without heartbeat churn.
|
|
# Notes: Nearby daytime rain or lightning starts a five-minute NOAA radar view; the ambient banner offers daylight replay while the event remains active.
|
|
# Notes: Actionable Kitchen banner slides open one shared short-lived detail surface; camera events retain priority.
|
|
# Notes: Phyn detail can restore a closed main valve only after an explicit on-screen confirmation.
|
|
# Notes: Rheem faults outrank low-hot-water reminders and reuse the hot-water diagnostic detail surface.
|
|
# Video: https://youtu.be/ChgEu0IDWzc
|
|
######################################################################
|
|
|
|
input_text:
|
|
kitchen_kiosk_detail_view:
|
|
name: "Kitchen Kiosk Detail View"
|
|
initial: none
|
|
max: 128
|
|
|
|
timer:
|
|
kitchen_kiosk_radar_display:
|
|
name: "Kitchen Kiosk Radar Display"
|
|
duration: "00:05:00"
|
|
restore: true
|
|
icon: mdi:radar
|
|
kitchen_kiosk_detail_display:
|
|
name: "Kitchen Kiosk Detail Display"
|
|
duration: "00:03:00"
|
|
restore: false
|
|
icon: mdi:card-text-outline
|
|
|
|
automation:
|
|
- alias: "Bedroom Kiosk Tablet - Return to Kiosk View"
|
|
id: 11e50d2e-f66f-4fd0-86f4-bdca075c3a1c
|
|
mode: single
|
|
max_exceeded: silent
|
|
trigger:
|
|
- platform: state
|
|
entity_id: switch.alarm_panel_1_screen
|
|
to: "on"
|
|
for: "00:00:03"
|
|
id: wake
|
|
- platform: state
|
|
entity_id: switch.alarm_panel_1_screensaver
|
|
to: "off"
|
|
for: "00:00:03"
|
|
id: wake
|
|
- platform: state
|
|
entity_id:
|
|
- sensor.alarm_panel_1_current_page
|
|
- sensor.alarm_panel_1_foreground_app
|
|
- number.alarm_panel_1_screen_brightness
|
|
for: "00:00:10"
|
|
id: drift
|
|
- platform: time_pattern
|
|
minutes: "/1"
|
|
id: periodic
|
|
- platform: homeassistant
|
|
event: start
|
|
id: startup
|
|
|
|
condition:
|
|
- condition: state
|
|
entity_id: switch.alarm_panel_1_screen
|
|
state: "on"
|
|
- condition: state
|
|
entity_id: switch.alarm_panel_1_screensaver
|
|
state: "off"
|
|
- condition: template
|
|
value_template: >-
|
|
{% set current_page = states('sensor.alarm_panel_1_current_page') %}
|
|
{% set foreground_app = states('sensor.alarm_panel_1_foreground_app') %}
|
|
{% set brightness = states('number.alarm_panel_1_screen_brightness') %}
|
|
{% set bed_clear = is_state('binary_sensor.sleepnumber_carlo_carlo_is_in_bed', 'off')
|
|
and is_state('binary_sensor.sleepnumber_carlo_stacey_is_in_bed', 'off') %}
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{{ (current_page not in invalid and '/local/bedroom-kiosk.html' not in current_page)
|
|
or (foreground_app not in invalid and foreground_app != 'de.ozerov.fully')
|
|
or (bed_clear and brightness not in invalid and brightness | float(100) < 40) }}
|
|
|
|
action:
|
|
- choose:
|
|
- conditions:
|
|
- condition: trigger
|
|
id: startup
|
|
sequence:
|
|
- delay: "00:02:00"
|
|
- variables:
|
|
previous_page: "{{ states('sensor.alarm_panel_1_current_page') }}"
|
|
previous_app: "{{ states('sensor.alarm_panel_1_foreground_app') }}"
|
|
previous_brightness: "{{ states('number.alarm_panel_1_screen_brightness') }}"
|
|
invalid:
|
|
- unknown
|
|
- unavailable
|
|
- none
|
|
- ""
|
|
- variables:
|
|
brightness_low: >-
|
|
{{ is_state('binary_sensor.sleepnumber_carlo_carlo_is_in_bed', 'off')
|
|
and is_state('binary_sensor.sleepnumber_carlo_stacey_is_in_bed', 'off')
|
|
and previous_brightness not in invalid
|
|
and previous_brightness | float(100) < 40 }}
|
|
foreground_drift: >-
|
|
{{ previous_app not in invalid and previous_app != 'de.ozerov.fully' }}
|
|
page_drift: >-
|
|
{{ previous_page not in invalid
|
|
and '/local/bedroom-kiosk.html' not in previous_page }}
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ brightness_low | bool }}"
|
|
sequence:
|
|
- service: number.set_value
|
|
target:
|
|
entity_id: number.alarm_panel_1_screen_brightness
|
|
data:
|
|
value: 100
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ foreground_drift | bool }}"
|
|
sequence:
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.alarm_panel_1_bring_to_foreground
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ page_drift | bool }}"
|
|
sequence:
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ foreground_drift | bool }}"
|
|
sequence:
|
|
- delay: "00:00:02"
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.alarm_panel_1_load_start_url
|
|
- service: script.send_to_logbook
|
|
data:
|
|
topic: "KIOSK"
|
|
message: >-
|
|
Bedroom tablet reloaded after page drift from
|
|
{{ previous_page }} (foreground app: {{ previous_app }};
|
|
brightness: {{ previous_brightness }}).
|
|
|
|
- alias: "Kitchen Kiosk Satellite - State Camera Policy"
|
|
id: 4c3ddc5b-1fe2-4c11-a77c-e2c15d374e77
|
|
mode: restart
|
|
trigger:
|
|
- platform: state
|
|
entity_id: sensor.kiosk_active_camera_view
|
|
|
|
condition:
|
|
- condition: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
state: "on"
|
|
|
|
action:
|
|
- service: script.kitchen_kiosk_apply_camera_policy
|
|
|
|
- alias: "Kitchen Kiosk Satellite - Screen Policy"
|
|
id: 99d8d43b-9448-4916-b313-8117a038baaf
|
|
mode: restart
|
|
trigger:
|
|
- platform: time
|
|
at: "08:00:00"
|
|
id: daily_volume
|
|
- platform: homeassistant
|
|
event: start
|
|
id: startup_volume
|
|
- platform: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
to: "on"
|
|
- platform: state
|
|
entity_id: light.kitchen_show_screen_2
|
|
to: "on"
|
|
- platform: state
|
|
entity_id: light.kitchen_show_screen_2
|
|
to: "off"
|
|
- platform: state
|
|
entity_id: binary_sensor.kitchen_show_connectivity_2
|
|
to: "on"
|
|
id: startup_volume
|
|
- platform: state
|
|
entity_id: switch.kitchen_show_keep_screen_on_2
|
|
to: "off"
|
|
- platform: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
to: "off"
|
|
|
|
action:
|
|
- if:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ trigger is defined
|
|
and trigger.id in ['daily_volume', 'startup_volume'] }}
|
|
- condition: template
|
|
value_template: >-
|
|
{% set volume = states('number.kitchen_show_volume_2') %}
|
|
{{ volume not in ['unknown', 'unavailable', 'none', '']
|
|
and (volume | float(-1)) != 13.0 }}
|
|
then:
|
|
- service: number.set_value
|
|
target:
|
|
entity_id: number.kitchen_show_volume_2
|
|
data:
|
|
value: 13
|
|
- condition: template
|
|
value_template: >-
|
|
{{ states('binary_sensor.kitchen_kiosk_should_be_on') in ['on', 'off'] }}
|
|
- choose:
|
|
- conditions:
|
|
- condition: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
state: "on"
|
|
sequence:
|
|
# Keep Android from entering true panel-off and napping Wi-Fi.
|
|
# Kiosk Satellite's Dim screensaver still owns idle brightness.
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.kitchen_show_keep_screen_on_2
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: light.kitchen_show_screen_2
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_postpone_screensaver_2
|
|
- service: script.kitchen_kiosk_apply_camera_policy
|
|
default:
|
|
# This Crown build drops Wi-Fi in true panel-off, so preserve the
|
|
# reachable display session and let the Dim screensaver go dark.
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.kitchen_show_keep_screen_on_2
|
|
- service: timer.cancel
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_close_camera_view_2
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: light.kitchen_show_screen_2
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.kitchen_show_screensaver_active_2
|
|
|
|
- alias: "Kitchen Kiosk Satellite - Daylight Radar Trigger"
|
|
id: 411dc0c0-a291-48e7-a493-2481a8d9477d
|
|
description: "Show NOAA radar for five minutes when a nearby daytime rain or lightning event begins."
|
|
mode: restart
|
|
trigger:
|
|
- platform: state
|
|
entity_id: binary_sensor.kiosk_rain_radar_weather_event
|
|
to: "on"
|
|
|
|
condition:
|
|
- condition: state
|
|
entity_id: binary_sensor.kiosk_rain_radar_weather_event
|
|
state: "on"
|
|
- condition: state
|
|
entity_id: timer.kitchen_kiosk_radar_display
|
|
state: idle
|
|
|
|
action:
|
|
- service: script.kitchen_kiosk_show_event
|
|
data:
|
|
event_type: radar
|
|
|
|
- alias: "Kitchen Kiosk Satellite - Clear Detail View"
|
|
id: 17bef67a-f68e-4b57-b04c-c2b890fafb77
|
|
description: "Clear transient banner detail state after timeout or household shutdown."
|
|
mode: restart
|
|
trigger:
|
|
- platform: event
|
|
event_type: timer.finished
|
|
event_data:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
- platform: event
|
|
event_type: timer.cancelled
|
|
event_data:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
action:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.kitchen_kiosk_detail_view
|
|
data:
|
|
value: none
|
|
|
|
- alias: "Kitchen Kiosk Satellite - Refresh Systems Snapshot"
|
|
id: e920cab1-59d3-4d45-8aad-67170127504f
|
|
description: "Reconcile an active startup storm, then refresh the Systems dashboard screenshot."
|
|
mode: single
|
|
max_exceeded: silent
|
|
trigger:
|
|
- platform: event
|
|
event_type: homeassistant_started
|
|
id: startup
|
|
- platform: time_pattern
|
|
minutes: "/15"
|
|
id: periodic
|
|
action:
|
|
- delay: "{{ '00:03:00' if trigger.id == 'startup' else '00:00:00' }}"
|
|
- choose:
|
|
- conditions:
|
|
- condition: trigger
|
|
id: startup
|
|
sequence:
|
|
- service: automation.trigger
|
|
target:
|
|
entity_id: automation.kitchen_kiosk_satellite_daylight_radar_trigger
|
|
data:
|
|
skip_condition: false
|
|
- condition: template
|
|
value_template: >-
|
|
{% set last_seen = as_timestamp(states('sensor.kitchen_show_last_seen_2'), 0) %}
|
|
{{ last_seen > 0 and (as_timestamp(now()) - last_seen) < 300 }}
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_take_screenshot_2
|
|
|
|
- alias: "Kitchen Kiosk Satellite - Update Joanna Dispatch"
|
|
id: 199e30f0-e28c-4842-953d-a65bc4b4e1d3
|
|
description: "At 07:00, stage and dispatch Joanna daily while a Kiosk Satellite release remains pending for the Kitchen Show."
|
|
mode: single
|
|
max_exceeded: silent
|
|
trigger:
|
|
- platform: time
|
|
at: "07:00:00"
|
|
|
|
condition:
|
|
- condition: state
|
|
entity_id: update.kitchen_show_update_2
|
|
state: "on"
|
|
- condition: template
|
|
value_template: >-
|
|
{% set installed = state_attr('update.kitchen_show_update_2', 'installed_version') | default('', true) | string %}
|
|
{% set latest = state_attr('update.kitchen_show_update_2', 'latest_version') | default('', true) | string %}
|
|
{{ installed not in ['', 'unknown', 'unavailable']
|
|
and latest not in ['', 'unknown', 'unavailable']
|
|
and installed != latest }}
|
|
|
|
action:
|
|
- variables:
|
|
installed_version: >-
|
|
{{ state_attr('update.kitchen_show_update_2', 'installed_version') | default('unknown', true) }}
|
|
latest_version: >-
|
|
{{ state_attr('update.kitchen_show_update_2', 'latest_version') | default('unknown', true) }}
|
|
release_url: >-
|
|
{{ state_attr('update.kitchen_show_update_2', 'release_url') | default('not provided', true) }}
|
|
structured_request: |-
|
|
KITCHEN_KIOSK_SATELLITE_UPDATE_REQUEST
|
|
target_device=Kitchen Show
|
|
update_entity=update.kitchen_show_update_2
|
|
installed_version={{ installed_version }}
|
|
target_version={{ latest_version }}
|
|
release_url={{ release_url }}
|
|
authorization=This dispatch authorizes installing the pending Kiosk Satellite application update on the Kitchen Show only. Do not update LineageOS, Home Assistant, or unrelated applications and do not factory-reset or re-enroll the tablet.
|
|
required_action=Home Assistant already invoked update.install and allowed two minutes for the signed installer payload to stage. If the update is still pending, use the pre-authorized Joanna ops helper /opt/codex/bin/kitchen-kiosk-update --expected-version {{ latest_version }} to complete this Kiosk Satellite update over the existing LAN-only management path.
|
|
required_verification=Do not stop at a successful service call. Verify update.kitchen_show_update_2 reports installed_version equal to latest_version, in_progress is false, the Kitchen Show returns online, sensor.kitchen_show_current_page_2 is the expected kiosk dashboard, sensor.kitchen_show_remote_admin_2 is available, and a fresh screenshot can be requested.
|
|
failure_policy=If the signed release cannot be installed safely or the device does not recover, stop without changing unrelated software and report the blocking evidence.
|
|
- service: update.install
|
|
continue_on_error: true
|
|
target:
|
|
entity_id: update.kitchen_show_update_2
|
|
- delay: "00:02:00"
|
|
- condition: state
|
|
entity_id: update.kitchen_show_update_2
|
|
state: "on"
|
|
- service: script.send_to_logbook
|
|
data:
|
|
topic: "KIOSK"
|
|
message: >-
|
|
Home Assistant staged and Joanna dispatched Kitchen Show Kiosk Satellite from
|
|
{{ installed_version }} to {{ latest_version }}.
|
|
- service: script.joanna_dispatch
|
|
data:
|
|
trigger_context: "HA automation kitchen_kiosk_satellite_update_joanna_dispatch (Kitchen Kiosk Satellite - Update Joanna Dispatch)"
|
|
source: "home_assistant_automation.kitchen_kiosk_satellite_update_dispatch"
|
|
summary: >-
|
|
Kiosk Satellite {{ latest_version }} is available for Kitchen Show;
|
|
installed version is {{ installed_version }}.
|
|
request: "{{ structured_request }}"
|
|
entity_ids:
|
|
- update.kitchen_show_update_2
|
|
- sensor.kitchen_show_last_seen_2
|
|
- sensor.kitchen_show_current_page_2
|
|
- sensor.kitchen_show_remote_admin_2
|
|
- button.kitchen_show_take_screenshot_2
|
|
diagnostics: >-
|
|
update_state={{ states('update.kitchen_show_update_2') }};
|
|
in_progress={{ state_attr('update.kitchen_show_update_2', 'in_progress') }};
|
|
last_seen={{ states('sensor.kitchen_show_last_seen_2') }};
|
|
current_page={{ states('sensor.kitchen_show_current_page_2') }};
|
|
remote_admin={{ states('sensor.kitchen_show_remote_admin_2') }}
|
|
template:
|
|
- sensor:
|
|
- name: "Kiosk Active Camera View"
|
|
unique_id: kiosk_active_camera_view
|
|
icon: mdi:camera-switch
|
|
state: >-
|
|
{% if is_state('binary_sensor.kiosk_garage_camera_active', 'on') %}
|
|
garage
|
|
{% elif is_state('lock.front_door', 'unlocked') %}
|
|
front_door
|
|
{% else %}
|
|
none
|
|
{% endif %}
|
|
|
|
- name: "Bedroom Kiosk Header"
|
|
unique_id: bedroom_kiosk_header
|
|
icon: mdi:bed-clock
|
|
state: >-
|
|
{% set alarm = states('sensor.bedroom_next_wake_alarm') %}
|
|
{% set alarm_ts = as_timestamp(alarm, none) %}
|
|
{% set alarm_source = states('sensor.bedroom_next_wake_alarm_source')
|
|
| replace(' Bedroom', '') %}
|
|
{% if alarm_ts is not none %}
|
|
NEXT ALARM - {{ alarm_source }} · {{ alarm_ts | timestamp_custom('%a %-I:%M %p') }}
|
|
{% else %}
|
|
NO BEDROOM WAKE ALARM SET
|
|
{% endif %}
|
|
attributes:
|
|
detail: >-
|
|
{% set weather = states('weather.pirateweather') | replace('_', ' ') | title %}
|
|
{% set temperature = state_attr('weather.pirateweather', 'temperature') %}
|
|
{% set secure = is_state('group.garage_doors', 'closed')
|
|
and is_state('group.locks', 'locked')
|
|
and is_state('group.entry_points', 'off') %}
|
|
{{ 'House secured' if secure else 'Check house security' }} ·
|
|
{{ temperature | round(0) if temperature is number else '--' }}° · {{ weather }}
|
|
|
|
- name: "Kiosk Household Alert"
|
|
unique_id: kiosk_household_alert
|
|
icon: mdi:message-alert-outline
|
|
state: >-
|
|
{% set alerts = state_attr('sensor.nws_alerts_alerts', 'Alerts') | default([], true) %}
|
|
{% set hot_water = states('sensor.rheem_wh_available_hot_water') | float(100) %}
|
|
{% set rheem_alert_count = states('sensor.rheem_wh_alert_count') | int(0) %}
|
|
{% set tomorrow = (now() + timedelta(days=1)).strftime('%Y-%m-%d') %}
|
|
{% set battery = states('sensor.spaceship_battery_level') | float(100) %}
|
|
{% set ns = namespace(name='', raw='') %}
|
|
{% for name, person, location in [
|
|
('Carlo', 'person.carlo', 'sensor.carlo_location_display'),
|
|
('Stacey', 'person.stacey', 'sensor.stacey_location_display'),
|
|
('Justin', 'person.justin', 'sensor.justin_location_display'),
|
|
('Paige', 'person.paige', 'sensor.paige_location_display')
|
|
] %}
|
|
{% if not ns.name and states(person) not in ['home', 'unknown', 'unavailable'] %}
|
|
{% set ns.name = name %}
|
|
{% set ns.raw = states(location) if states(location) not in ['unknown', 'unavailable'] else states(person) %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% if alerts | count > 0 %}
|
|
WEATHER ALERT - {{ alerts[0].Event | default('National Weather Service') }}
|
|
{% elif is_state('binary_sensor.front_door_packages_present', 'on') %}
|
|
PACKAGE AT THE FRONT DOOR
|
|
{% elif is_state('group.entry_points', 'on') %}
|
|
ENTRY POINT OPEN
|
|
{% elif states('group.locks') not in ['locked', 'unknown', 'unavailable'] %}
|
|
CHECK THE FRONT DOOR LOCK
|
|
{% elif rheem_alert_count > 0 %}
|
|
WATER HEATER ALERT - {{ rheem_alert_count }} ACTIVE
|
|
{% elif hot_water < 30 %}
|
|
HOT WATER IS RUNNING LOW
|
|
{% elif now().strftime('%a') in ['Wed', 'Sun']
|
|
and not is_state('input_boolean.garbage_cans_out', 'on') %}
|
|
{{ 'GARBAGE + RECYCLING' if now().strftime('%a') == 'Wed' else 'GARBAGE' }} DAY
|
|
{% elif states('input_datetime.water_delivery_date') == tomorrow %}
|
|
WATER DELIVERY TOMORROW
|
|
{% elif battery < 50 and is_state('switch.spaceship_charge', 'off')
|
|
and is_state('person.carlo', 'home') and is_state('person.stacey', 'home') %}
|
|
PLUG IN THE TESLA
|
|
{% elif ns.name %}
|
|
{% set location = ns.raw | replace(ns.name ~ ' ', '') %}
|
|
{{ ns.name }} - {{ location.split(' (since ')[0] }}
|
|
{% else %}
|
|
EVERYTHING IS HANDLED
|
|
{% endif %}
|
|
attributes:
|
|
detail: >-
|
|
{% set alerts = state_attr('sensor.nws_alerts_alerts', 'Alerts') | default([], true) %}
|
|
{% set hot_water = states('sensor.rheem_wh_available_hot_water') | float(100) %}
|
|
{% set rheem_alert_count = states('sensor.rheem_wh_alert_count') | int(0) %}
|
|
{% set tomorrow = (now() + timedelta(days=1)).strftime('%Y-%m-%d') %}
|
|
{% set battery = states('sensor.spaceship_battery_level') | float(100) %}
|
|
{% set ns = namespace(name='', raw='') %}
|
|
{% for name, person, location in [
|
|
('Carlo', 'person.carlo', 'sensor.carlo_location_display'),
|
|
('Stacey', 'person.stacey', 'sensor.stacey_location_display'),
|
|
('Justin', 'person.justin', 'sensor.justin_location_display'),
|
|
('Paige', 'person.paige', 'sensor.paige_location_display')
|
|
] %}
|
|
{% if not ns.name and states(person) not in ['home', 'unknown', 'unavailable'] %}
|
|
{% set ns.name = name %}
|
|
{% set ns.raw = states(location) if states(location) not in ['unknown', 'unavailable'] else states(person) %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% if alerts | count > 0 %}
|
|
{{ (alerts[0].Headline | default(alerts[0].Description, true))
|
|
| replace('\n', ' ') | truncate(300, true) }}
|
|
{% elif is_state('binary_sensor.front_door_packages_present', 'on') %}
|
|
Remember to bring it inside.
|
|
{% elif is_state('group.entry_points', 'on') %}
|
|
Check the exterior doors and windows.
|
|
{% elif states('group.locks') not in ['locked', 'unknown', 'unavailable'] %}
|
|
Lock status is {{ states('group.locks') | replace('_', ' ') }}.
|
|
{% elif rheem_alert_count > 0 %}
|
|
Rheem reports {{ rheem_alert_count }} active {{ 'alert' if rheem_alert_count == 1 else 'alerts' }}.
|
|
Status is {{ states('sensor.rheem_wh_diagnostic_status') | replace('_', ' ') }}.
|
|
Check Home Assistant Repairs for the diagnostic snapshot.
|
|
{% elif hot_water < 30 %}
|
|
{{ hot_water | round(0) }}% is available - keep showers short.
|
|
{% elif now().strftime('%a') in ['Wed', 'Sun']
|
|
and not is_state('input_boolean.garbage_cans_out', 'on') %}
|
|
Put the cans at the curb.
|
|
{% elif states('input_datetime.water_delivery_date') == tomorrow %}
|
|
Put the empty bottles out.
|
|
{% elif battery < 50 and is_state('switch.spaceship_charge', 'off')
|
|
and is_state('person.carlo', 'home') and is_state('person.stacey', 'home') %}
|
|
Model Y battery is {{ battery | round(0) }}%.
|
|
{% elif ns.name %}
|
|
{% set parts = ns.raw.split(' (since ') %}
|
|
{{ 'Since ' ~ (parts[1] | replace(')', '')) if parts | count > 1 else 'Away from home' }}
|
|
{% else %}
|
|
No active household alerts or reminders.
|
|
{% endif %}
|
|
|
|
- binary_sensor:
|
|
- name: "Kiosk Garage Camera Active"
|
|
unique_id: kiosk_garage_camera_active
|
|
icon: mdi:garage-alert
|
|
delay_off: "00:03:00"
|
|
state: >-
|
|
{{ states('cover.large_garage_door') in ['opening', 'open', 'closing']
|
|
or states('cover.small_garage_door') in ['opening', 'open', 'closing'] }}
|
|
|
|
- name: "Kiosk Rain Radar Weather Event"
|
|
unique_id: kiosk_rain_radar_weather_event
|
|
icon: mdi:radar
|
|
delay_on: "00:02:00"
|
|
state: >-
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{% set precip = states('sensor.pirateweather_precip') | lower %}
|
|
{% set intensity = states('sensor.pirateweather_precip_intensity') | float(0) %}
|
|
{% set storm_distance_state = states('sensor.pirateweather_nearest_storm_distance') %}
|
|
{% set storm_distance_miles = storm_distance_state | float(999) %}
|
|
{% set lightning_count = states('sensor.blitzortung_lightning_counter') | int(0) %}
|
|
{% set lightning_distance_state = states('sensor.blitzortung_lightning_distance') %}
|
|
{% set lightning_distance_miles = lightning_distance_state | float(9999) / 1.609344 %}
|
|
{{ is_state('binary_sensor.kitchen_kiosk_should_be_on', 'on')
|
|
and is_state('sun.sun', 'above_horizon')
|
|
and (
|
|
precip == 'rain'
|
|
or intensity > 0.2
|
|
or (storm_distance_state not in invalid and storm_distance_miles <= 10)
|
|
or (lightning_count > 0
|
|
and lightning_distance_state not in invalid
|
|
and lightning_distance_miles <= 10)
|
|
) }}
|
|
|
|
- name: "Kiosk Rain Radar Active"
|
|
unique_id: kiosk_rain_radar_active
|
|
icon: mdi:radar
|
|
state: >-
|
|
{{ is_state('binary_sensor.kitchen_kiosk_should_be_on', 'on')
|
|
and is_state('sun.sun', 'above_horizon')
|
|
and is_state('timer.kitchen_kiosk_radar_display', 'active') }}
|
|
|
|
- name: "Kitchen Kiosk Should Be On"
|
|
unique_id: kitchen_kiosk_should_be_on
|
|
icon: mdi:monitor-eye
|
|
state: >-
|
|
{% set guest = is_state('input_boolean.guest_mode', 'on') %}
|
|
{% set sitter = is_state('input_boolean.house_sitter_present', 'on') %}
|
|
{% set family_home = is_state('group.family', 'home') %}
|
|
{% set carlo_bed = is_state('binary_sensor.sleepnumber_carlo_carlo_is_in_bed', 'on') %}
|
|
{% set stacey_bed = is_state('binary_sensor.sleepnumber_carlo_stacey_is_in_bed', 'on') %}
|
|
{% set bedtime = (carlo_bed or stacey_bed)
|
|
and (carlo_bed or is_state('person.carlo', 'not_home'))
|
|
and (stacey_bed or is_state('person.stacey', 'not_home')) %}
|
|
{{ guest or sitter or (family_home and not bedtime) }}
|
|
attributes:
|
|
reason: >-
|
|
{% if is_state('input_boolean.guest_mode', 'on') %}
|
|
guest mode
|
|
{% elif is_state('input_boolean.house_sitter_present', 'on') %}
|
|
house sitter present
|
|
{% elif not is_state('group.family', 'home') %}
|
|
nobody home
|
|
{% elif is_state('binary_sensor.sleepnumber_carlo_carlo_is_in_bed', 'on')
|
|
and is_state('binary_sensor.sleepnumber_carlo_stacey_is_in_bed', 'on') %}
|
|
household asleep
|
|
{% elif is_state('binary_sensor.sleepnumber_carlo_carlo_is_in_bed', 'on')
|
|
and is_state('person.stacey', 'not_home') %}
|
|
Carlo asleep and Stacey away
|
|
{% elif is_state('binary_sensor.sleepnumber_carlo_stacey_is_in_bed', 'on')
|
|
and is_state('person.carlo', 'not_home') %}
|
|
Stacey asleep and Carlo away
|
|
{% else %}
|
|
household active
|
|
{% endif %}
|
|
|
|
- name: "Bedroom Kiosk Needs Attention"
|
|
unique_id: bedroom_kiosk_needs_attention
|
|
device_class: problem
|
|
icon: mdi:tablet-alert
|
|
delay_on: "00:02:00"
|
|
delay_off: "00:00:30"
|
|
state: >-
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{% set page = states('sensor.alarm_panel_1_current_page') %}
|
|
{% set app = states('sensor.alarm_panel_1_foreground_app') %}
|
|
{% set battery = states('sensor.alarm_panel_1_battery') | float(0) %}
|
|
{{ page in invalid
|
|
or app in invalid
|
|
or '/local/bedroom-kiosk.html' not in page
|
|
or app != 'de.ozerov.fully'
|
|
or (battery < 20 and not is_state('binary_sensor.alarm_panel_1_plugged_in', 'on')) }}
|
|
attributes:
|
|
status: >-
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{% set page = states('sensor.alarm_panel_1_current_page') %}
|
|
{% set app = states('sensor.alarm_panel_1_foreground_app') %}
|
|
{% set battery = states('sensor.alarm_panel_1_battery') | float(0) %}
|
|
{% if page in invalid or app in invalid %}
|
|
offline
|
|
{% elif '/local/bedroom-kiosk.html' not in page %}
|
|
page drift
|
|
{% elif app != 'de.ozerov.fully' %}
|
|
app drift
|
|
{% elif battery < 20 and not is_state('binary_sensor.alarm_panel_1_plugged_in', 'on') %}
|
|
low battery
|
|
{% else %}
|
|
online
|
|
{% endif %}
|
|
|
|
- name: "Kitchen Kiosk Needs Attention"
|
|
unique_id: kitchen_kiosk_needs_attention
|
|
device_class: problem
|
|
icon: mdi:monitor-alert
|
|
delay_on: "00:02:00"
|
|
delay_off: "00:00:30"
|
|
state: >-
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{% set screenshot = as_timestamp(states('sensor.kitchen_show_last_screenshot_2'), 0) %}
|
|
{% set page = states('sensor.kitchen_show_current_page_2') %}
|
|
{% set remote_admin = states('sensor.kitchen_show_remote_admin_2') %}
|
|
{% set connectivity = states('binary_sensor.kitchen_show_connectivity_2') %}
|
|
{% set battery = states('sensor.kitchen_show_battery_2') | float(0) %}
|
|
{% set device_offline = connectivity != 'on' %}
|
|
{% set screenshot_stale = screenshot == 0 or (as_timestamp(now()) - screenshot) > 2700 %}
|
|
{{ device_offline
|
|
or page in invalid
|
|
or remote_admin in invalid
|
|
or '/dashboard-kiosk-satellite-staging/home' not in page
|
|
or (battery < 20 and not is_state('binary_sensor.kitchen_show_charging_2', 'on'))
|
|
or screenshot_stale }}
|
|
attributes:
|
|
status: >-
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{% set screenshot = as_timestamp(states('sensor.kitchen_show_last_screenshot_2'), 0) %}
|
|
{% set page = states('sensor.kitchen_show_current_page_2') %}
|
|
{% set remote_admin = states('sensor.kitchen_show_remote_admin_2') %}
|
|
{% set connectivity = states('binary_sensor.kitchen_show_connectivity_2') %}
|
|
{% set battery = states('sensor.kitchen_show_battery_2') | float(0) %}
|
|
{% if connectivity != 'on' %}
|
|
offline
|
|
{% elif page in invalid or remote_admin in invalid %}
|
|
telemetry unavailable
|
|
{% elif '/dashboard-kiosk-satellite-staging/home' not in page %}
|
|
page drift
|
|
{% elif battery < 20 and not is_state('binary_sensor.kitchen_show_charging_2', 'on') %}
|
|
low battery
|
|
{% elif screenshot == 0 or (as_timestamp(now()) - screenshot) > 2700 %}
|
|
screenshot stale
|
|
{% elif is_state('update.kitchen_show_update_2', 'on') %}
|
|
update available
|
|
{% else %}
|
|
online
|
|
{% endif %}
|
|
|
|
- name: "Kiosk Devices Need Attention"
|
|
unique_id: kiosk_devices_need_attention
|
|
device_class: problem
|
|
icon: mdi:tablet-cellphone
|
|
state: >-
|
|
{{ is_state('binary_sensor.bedroom_kiosk_needs_attention', 'on')
|
|
or is_state('binary_sensor.kitchen_kiosk_needs_attention', 'on') }}
|
|
attributes:
|
|
status: >-
|
|
{% set bedroom = is_state('binary_sensor.bedroom_kiosk_needs_attention', 'on') %}
|
|
{% set kitchen = is_state('binary_sensor.kitchen_kiosk_needs_attention', 'on') %}
|
|
{% if bedroom and kitchen %}
|
|
Bedroom and Kitchen need attention
|
|
{% elif bedroom %}
|
|
Bedroom needs attention
|
|
{% elif kitchen %}
|
|
Kitchen needs attention
|
|
{% else %}
|
|
All kiosks online
|
|
{% endif %}
|
|
devices: >-
|
|
{% set ns = namespace(items=[]) %}
|
|
{% if is_state('binary_sensor.bedroom_kiosk_needs_attention', 'on') %}
|
|
{% set ns.items = ns.items + ['Bedroom'] %}
|
|
{% endif %}
|
|
{% if is_state('binary_sensor.kitchen_kiosk_needs_attention', 'on') %}
|
|
{% set ns.items = ns.items + ['Kitchen'] %}
|
|
{% endif %}
|
|
{{ ns.items }}
|
|
|
|
script:
|
|
kitchen_kiosk_apply_camera_policy:
|
|
alias: "Kitchen Kiosk - Apply Camera Policy"
|
|
mode: restart
|
|
variables:
|
|
desired_view: >-
|
|
{{ {'garage': 'Garage', 'front_door': 'Front Door'}.get(
|
|
states('sensor.kiosk_active_camera_view'), 'none') }}
|
|
desired_button: >-
|
|
{{ 'button.kitchen_show_show_garage_2'
|
|
if desired_view == 'Garage'
|
|
else 'button.kitchen_show_show_front_door_2' }}
|
|
sequence:
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ desired_view in ['Garage', 'Front Door'] }}"
|
|
sequence:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ states('sensor.kitchen_show_active_camera_view_2') != desired_view }}
|
|
- service: script.kitchen_kiosk_show_event
|
|
data:
|
|
event_type: camera
|
|
show_button: "{{ desired_button }}"
|
|
default:
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ states('sensor.kitchen_show_active_camera_view_2')
|
|
not in ['none', 'unknown', 'unavailable'] }}
|
|
sequence:
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_close_camera_view_2
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_bring_to_front_2
|
|
|
|
kitchen_kiosk_show_event:
|
|
alias: "Kitchen Kiosk - Show Display Event"
|
|
mode: restart
|
|
fields:
|
|
event_type:
|
|
name: Event type
|
|
description: Event renderer to show on the Kitchen kiosk.
|
|
required: true
|
|
selector:
|
|
select:
|
|
options:
|
|
- radar
|
|
- camera
|
|
- detail
|
|
show_button:
|
|
name: Camera view button
|
|
description: Kiosk Satellite MQTT button for the native camera view.
|
|
required: false
|
|
selector:
|
|
entity:
|
|
domain: button
|
|
sequence:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ event_type in ['camera', 'detail']
|
|
or (
|
|
event_type == 'radar'
|
|
and is_state('binary_sensor.kitchen_kiosk_should_be_on', 'on')
|
|
and is_state('sun.sun', 'above_horizon')
|
|
and is_state('binary_sensor.kiosk_rain_radar_weather_event', 'on')
|
|
) }}
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: light.kitchen_show_screen_2
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_postpone_screensaver_2
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_bring_to_front_2
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ event_type == 'radar' }}"
|
|
sequence:
|
|
- service: timer.cancel
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
- service: timer.start
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_radar_display
|
|
data:
|
|
duration: "00:05:00"
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ event_type == 'camera' }}"
|
|
sequence:
|
|
- service: timer.cancel
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
- condition: template
|
|
value_template: >-
|
|
{{ show_button is defined and show_button | string | length > 0 }}
|
|
- delay: "00:00:01"
|
|
- service: button.press
|
|
target:
|
|
entity_id: "{{ show_button }}"
|
|
|
|
kitchen_kiosk_show_detail:
|
|
alias: "Kitchen Kiosk - Show Banner Detail"
|
|
mode: restart
|
|
fields:
|
|
detail_type:
|
|
name: Detail type
|
|
description: Contextual detail renderer requested by the active banner slide.
|
|
required: true
|
|
selector:
|
|
select:
|
|
options:
|
|
- weather
|
|
- package
|
|
- family
|
|
- entry_points
|
|
- phyn
|
|
- hot_water
|
|
detail_subject:
|
|
name: Detail subject
|
|
description: Optional alert ID or person entity for the detail renderer.
|
|
required: false
|
|
selector:
|
|
text:
|
|
variables:
|
|
normalized_type: "{{ detail_type | default('', true) | lower }}"
|
|
normalized_subject: "{{ detail_subject | default('', true) | string }}"
|
|
allowed_people:
|
|
- person.carlo
|
|
- person.stacey
|
|
- person.justin
|
|
- person.paige
|
|
phyn_alert_entities:
|
|
- binary_sensor.garage_phyn_battery_alert
|
|
- binary_sensor.garage_phyn_freeze_warning_alert
|
|
- binary_sensor.garage_phyn_high_pressure_alert
|
|
- binary_sensor.garage_phyn_leak_alert
|
|
- binary_sensor.garage_phyn_offline_leak_shutoff_alert
|
|
- binary_sensor.garage_phyn_pinhole_leak_alert
|
|
- binary_sensor.garage_phyn_recurring_flow_alert
|
|
- binary_sensor.garage_phyn_temperature_alert
|
|
detail_is_valid: >-
|
|
{% set phyn_alert = expand(phyn_alert_entities)
|
|
| selectattr('state', 'eq', 'on') | list | count > 0 %}
|
|
{{ is_state('binary_sensor.kitchen_kiosk_should_be_on', 'on')
|
|
and (
|
|
(normalized_type == 'weather' and states('sensor.nws_alerts_alerts') | int(0) > 0)
|
|
or (normalized_type == 'package' and is_state('binary_sensor.front_door_packages_present', 'on'))
|
|
or (normalized_type == 'family'
|
|
and normalized_subject in allowed_people
|
|
and states(normalized_subject) not in ['home', 'unknown', 'unavailable'])
|
|
or (normalized_type == 'entry_points' and is_state('group.entry_points', 'on'))
|
|
or (normalized_type == 'phyn'
|
|
and (phyn_alert or states('valve.phyn_shutoff_valve') != 'open'))
|
|
or (normalized_type == 'hot_water'
|
|
and (
|
|
is_state('binary_sensor.rheem_wh_problem', 'on')
|
|
or states('sensor.rheem_wh_available_hot_water') | float(100) < 30
|
|
))
|
|
) }}
|
|
detail_duration: >-
|
|
{{ '00:05:00' if normalized_type in ['weather', 'phyn'] else '00:03:00' }}
|
|
detail_value: >-
|
|
{{ normalized_type ~ ('|' ~ normalized_subject if normalized_subject | length > 0 else '') }}
|
|
sequence:
|
|
- condition: template
|
|
value_template: "{{ detail_is_valid }}"
|
|
- service: timer.cancel
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_radar_display
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.kitchen_kiosk_detail_view
|
|
data:
|
|
value: "{{ detail_value }}"
|
|
- service: timer.start
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
data:
|
|
duration: "{{ detail_duration }}"
|
|
- service: script.kitchen_kiosk_show_event
|
|
data:
|
|
event_type: detail
|
|
|
|
kitchen_kiosk_restore_phyn_water:
|
|
alias: "Kitchen Kiosk - Restore Phyn Water"
|
|
mode: single
|
|
sequence:
|
|
- condition: state
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
state: active
|
|
- condition: template
|
|
value_template: >-
|
|
{{ states('input_text.kitchen_kiosk_detail_view').split('|')[0] == 'phyn'
|
|
and is_state('valve.phyn_shutoff_valve', 'closed') }}
|
|
- service: valve.open_valve
|
|
target:
|
|
entity_id: valve.phyn_shutoff_valve
|
|
- service: script.send_to_logbook
|
|
data:
|
|
topic: WATER
|
|
message: "Kitchen Show requested that the Phyn main water valve be turned on."
|