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.

902 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 and remains for three minutes after both close; 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: >-
{% 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 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 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 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."

Powered by TurnKey Linux.