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.
898 lines
40 KiB
898 lines
40 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 camera policy
|
|
# Keeps the Bedroom tablet stable and drives state-based Kitchen Show camera views.
|
|
# -------------------------------------------------------------------
|
|
# Related Issue: 1875
|
|
# 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 discovery entities; no screensaver helper is required.
|
|
# Notes: Kitchen Show stays dark while the house is empty or asleep and wakes only for occupied-house events.
|
|
# Notes: Garage takes over while either door is moving/open; Front Door takes over while unlocked.
|
|
# Notes: At 07:00, a pending new Kiosk Satellite release dispatches Joanna once for install and verification.
|
|
# 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 last-seen/update/screenshot freshness 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.
|
|
# Video: https://youtu.be/ChgEu0IDWzc
|
|
######################################################################
|
|
|
|
input_text:
|
|
kitchen_show_kiosk_satellite_last_dispatched_version:
|
|
name: "Kitchen Show Kiosk Satellite Last Dispatched Version"
|
|
max: 32
|
|
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: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
to: "on"
|
|
- platform: state
|
|
entity_id: light.kitchen_show_screen
|
|
to: "on"
|
|
- platform: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
to: "off"
|
|
|
|
action:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ states('binary_sensor.kitchen_kiosk_should_be_on') in ['on', 'off'] }}
|
|
- variables:
|
|
desired_volume: >-
|
|
{{ 10 if is_state('binary_sensor.kitchen_kiosk_should_be_on', 'on') else 0 }}
|
|
# Android reports the nearest hardware volume step (13% for a 10% request).
|
|
- if:
|
|
- condition: template
|
|
value_template: >-
|
|
{{ (states('number.kitchen_show_volume') | int(-1)
|
|
- desired_volume | int(-1)) | abs > 3 }}
|
|
then:
|
|
- service: number.set_value
|
|
target:
|
|
entity_id: number.kitchen_show_volume
|
|
data:
|
|
value: "{{ desired_volume | int(0) }}"
|
|
- choose:
|
|
- conditions:
|
|
- condition: state
|
|
entity_id: binary_sensor.kitchen_kiosk_should_be_on
|
|
state: "on"
|
|
sequence:
|
|
# Kiosk Satellite owns idle dimming. This event-driven dismiss
|
|
# wakes to the dashboard without a poller repeatedly forcing the
|
|
# panel on during an occupied day.
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_postpone_screensaver
|
|
- service: script.kitchen_kiosk_apply_camera_policy
|
|
default:
|
|
- service: timer.cancel
|
|
target:
|
|
entity_id: timer.kitchen_kiosk_detail_display
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_close_camera_view
|
|
- service: light.turn_off
|
|
target:
|
|
entity_id: light.kitchen_show_screen
|
|
|
|
- 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'), 0) %}
|
|
{{ last_seen > 0 and (as_timestamp(now()) - last_seen) < 300 }}
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_take_screenshot
|
|
|
|
- alias: "Kitchen Kiosk Satellite - Update Joanna Dispatch"
|
|
id: 199e30f0-e28c-4842-953d-a65bc4b4e1d3
|
|
description: "At 07:00, dispatch Joanna once when a new Kiosk Satellite release is 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
|
|
state: "on"
|
|
- condition: template
|
|
value_template: >-
|
|
{% set installed = state_attr('update.kitchen_show_update', 'installed_version') | default('', true) | string %}
|
|
{% set latest = state_attr('update.kitchen_show_update', 'latest_version') | default('', true) | string %}
|
|
{{ installed not in ['', 'unknown', 'unavailable']
|
|
and latest not in ['', 'unknown', 'unavailable']
|
|
and installed != latest
|
|
and latest != states('input_text.kitchen_show_kiosk_satellite_last_dispatched_version') }}
|
|
|
|
action:
|
|
- variables:
|
|
installed_version: >-
|
|
{{ state_attr('update.kitchen_show_update', 'installed_version') | default('unknown', true) }}
|
|
latest_version: >-
|
|
{{ state_attr('update.kitchen_show_update', 'latest_version') | default('unknown', true) }}
|
|
release_url: >-
|
|
{{ state_attr('update.kitchen_show_update', 'release_url') | default('not provided', true) }}
|
|
structured_request: |-
|
|
KITCHEN_KIOSK_SATELLITE_UPDATE_REQUEST
|
|
target_device=Kitchen Show
|
|
update_entity=update.kitchen_show_update
|
|
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=Inspect the live update entity and device availability, invoke the supported Home Assistant update.install action, and observe whether installation actually begins. If Android does not finish the installation, use the pre-authorized Joanna ops helper /opt/codex/bin/kitchen-kiosk-update --expected-version {{ latest_version }} to complete this same signed 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 reports installed_version equal to latest_version, in_progress is false, the Kitchen Show returns online, sensor.kitchen_show_current_page is the expected kiosk dashboard, sensor.kitchen_show_remote_admin 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: script.send_to_logbook
|
|
data:
|
|
topic: "KIOSK"
|
|
message: >-
|
|
Joanna dispatched to update 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
|
|
- sensor.kitchen_show_last_seen
|
|
- sensor.kitchen_show_current_page
|
|
- sensor.kitchen_show_remote_admin
|
|
- button.kitchen_show_take_screenshot
|
|
diagnostics: >-
|
|
update_state={{ states('update.kitchen_show_update') }};
|
|
in_progress={{ state_attr('update.kitchen_show_update', 'in_progress') }};
|
|
last_seen={{ states('sensor.kitchen_show_last_seen') }};
|
|
current_page={{ states('sensor.kitchen_show_current_page') }};
|
|
remote_admin={{ states('sensor.kitchen_show_remote_admin') }}
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.kitchen_show_kiosk_satellite_last_dispatched_version
|
|
data:
|
|
value: "{{ latest_version }}"
|
|
|
|
template:
|
|
- sensor:
|
|
- name: "Kiosk Active Camera View"
|
|
unique_id: kiosk_active_camera_view
|
|
icon: mdi:camera-switch
|
|
state: >-
|
|
{% set garage_states = [
|
|
states('cover.large_garage_door'),
|
|
states('cover.small_garage_door')
|
|
] %}
|
|
{% if garage_states | select('in', ['opening', 'open', 'closing']) | list | count > 0 %}
|
|
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 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 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 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 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 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 last_seen = as_timestamp(states('sensor.kitchen_show_last_seen'), 0) %}
|
|
{% set screenshot = as_timestamp(states('sensor.kitchen_show_last_screenshot'), 0) %}
|
|
{% set page = states('sensor.kitchen_show_current_page') %}
|
|
{% set remote_admin = states('sensor.kitchen_show_remote_admin') %}
|
|
{% set battery = states('sensor.kitchen_show_battery') | float(0) %}
|
|
{% set offline = last_seen == 0 or (as_timestamp(now()) - last_seen) > 300 %}
|
|
{% set screenshot_stale = screenshot == 0 or (as_timestamp(now()) - screenshot) > 2700 %}
|
|
{{ 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', 'on'))
|
|
or screenshot_stale }}
|
|
attributes:
|
|
status: >-
|
|
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
|
|
{% set last_seen = as_timestamp(states('sensor.kitchen_show_last_seen'), 0) %}
|
|
{% set screenshot = as_timestamp(states('sensor.kitchen_show_last_screenshot'), 0) %}
|
|
{% set page = states('sensor.kitchen_show_current_page') %}
|
|
{% set remote_admin = states('sensor.kitchen_show_remote_admin') %}
|
|
{% set battery = states('sensor.kitchen_show_battery') | float(0) %}
|
|
{% if last_seen == 0 or (as_timestamp(now()) - last_seen) > 300 %}
|
|
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', 'on') %}
|
|
low battery
|
|
{% elif screenshot == 0 or (as_timestamp(now()) - screenshot) > 2700 %}
|
|
screenshot stale
|
|
{% elif is_state('update.kitchen_show_update', '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'
|
|
if desired_view == 'Garage'
|
|
else 'button.kitchen_show_show_front_door' }}
|
|
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') != 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')
|
|
not in ['none', 'unknown', 'unavailable'] }}
|
|
sequence:
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_close_camera_view
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_bring_to_front
|
|
|
|
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
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_postpone_screensaver
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.kitchen_show_bring_to_front
|
|
- 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 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."
|