# Update the master speaker in the group
- service: input_select.select_option
entity_id: input_select.music_controller
data:
option: >
{% set ns = namespace() %}
{% set ns.primary_speaker = 'none' %}
{% set ns.secondary_speaker = 'none' %}
{# set the pri_speaker and sec_speaker #}
{% for speaker in state_attr(target_player, "sonos_group") %}
{% if loop.index == 1 %}
{% set ns.primary_speaker = speaker|regex_replace(find='media_player.', replace='', ignorecase=False) %}
{% elif loop.index == 2 %}
{% set ns.secondary_speaker = speaker|regex_replace(find='media_player.', replace='', ignorecase=False) %}
{% endif %}
{% endfor %}
{# use the second speaker as master speaker if target speaker is currently the master #}
{% if target_player == ('media_player.' + ns.primary_speaker) and ns.secondary_speaker != 'none' %}
{{ ns.secondary_speaker }}
{% else %}
{{ ns.primary_speaker }}
{% endif %}
- condition: template
value_template: >
{% set num_seconds_ago = now().timestamp() - states.switch.gaming_pc.last_changed.timestamp() %}
{% set num_hours_ago = (num_seconds_ago/3600)|int %}
{% set timer = states('input_number.gaming_pc_shutdown_timer_in_hour')|int %}
{{num_hours_ago >= timer and is_state('switch.gaming_pc', 'on')}}
然而同样的jinja的内容也可以用python实现
@service
def turn_off_gaming_pc_based_on_a_timer():
# Duration of the current gaming_pc state
from datetime import datetime as dt
from datetime import timezone as timezone
num_seconds_ago = (dt.now(tz=timezone.utc) - switch.gaming_pc.last_changed).total_seconds()
num_hours_ago = int(num_seconds_ago/3600)
# Cast of timer value
timer = int(float(input_number.gaming_pc_shutdown_timer_in_hour))
# If the gaming PC is on for more than timer value, turn off the pc
if num_hours_ago >= timer and switch.gaming_pc == 'on':
#some actions
import datetime
# Get the number of seconds this entity has been current state
def get_sec_of_cur_state(entity_name):
last_time_cur_entity_changed = state.get(entity_name + '.last_changed')
return (datetime.datetime.now(tz=datetime.timezone.utc) - last_time_cur_entity_changed).total_seconds()
def now_is_before(hour, minute, second):
return datetime.datetime.now().time() < datetime.time(hour, minute, second)
def now_is_after(hour, minute, second):
return datetime.datetime.now().time() > datetime.time(hour, minute, second)
################################
# Room Occupancy
#
# outside --c0---> just_entered ----c2----> stayed ---c7-----> in_sleep
# |<----c3---------| | |
# |<-------------------c5-----------------|<------c10--------|
# |<----------------------------------------------c8---------|
# |c1| |c4| |c6| |c9|
#
# State machine changing conditions:
#
# c0. outside -> just_entered:
# c1. outside -> outside:
# c2. just_entered -> stayed:
# c3. just_entered -> outside:
# c4. just_entered -> just_entered
# c5. stayed -> outside:
# c6. stayed -> stayed:
# c7. stayed -> in_sleep:
# c8. in_sleep -> outside:
# c9. in_sleep -> in_sleep
#
################################
@service
def room_occupancy_state_machine(occupancy_entity_str,
motion_str,
motion_on_ratio_for_x_min_str,
motion_on_ratio_for_2x_min_str,
room_type):
#percentage_for_largely_def = 0.4
#percentage_for_fully_def = 0.8
# Get state based on string
cur_state = state.get(occupancy_entity_str)
motion = state.get(motion_str)
motion_state_lasts_for = get_sec_of_cur_state(motion_str)
motion_off_for = motion_state_lasts_for if motion == 'off' else 0
motion_on_ratio_for_x_min = float(state.get(motion_on_ratio_for_x_min_str))
motion_on_ratio_for_2x_min = float(state.get(motion_on_ratio_for_2x_min_str))
motion_off_ratio_for_x_min = 1 - motion_on_ratio_for_x_min
motion_off_ratio_for_2x_min= 1 - motion_on_ratio_for_2x_min
nxt_state = ''
stay_inside_for = get_sec_of_cur_state(occupancy_entity_str) if cur_state == 'Stayed Inside' else 0
now_is_sleep_time = now_is_before(9,30,0) or now_is_after(21,0,0)
# Outside -> xxx
if cur_state == 'Outside':
# c0. Outside -> Just Entered:
# currently on
if motion == 'on':
nxt_state = "Just Entered"
# c1. Outside -> Outside:
# currently off for 5 Min & previously off in [0, 2x]
# OR all other condition
else:
nxt_state = 'Outside'
# Just Entered -> xxx
elif cur_state == 'Just Entered':
# c2. Just Entered -> Stayed Inside:
# currently on & previously largely on in [0,x] or [0,2x]
if motion == 'on' and \
(motion_on_ratio_for_x_min >= 0.6 or
motion_on_ratio_for_2x_min >= 0.4):
nxt_state = "Stayed Inside"
# c3. Just Entered -> Outside:
# (currently off for 5min) & largely off in [0,2x]
elif motion == 'off' and \
motion_state_lasts_for >= 5*60 and \
motion_off_ratio_for_2x_min >= 0.5:
nxt_state = "Outside"
# c4. just_entered -> just_entered
# all other conditions
else:
nxt_state = "Just Entered"
# Stayed Inside -> xxx
elif cur_state == 'Stayed Inside':
# c7. Stayed Inside -> In Sleep:
# People is inside the room for an hour in the night time
# would assume they are in bed and ready for sleep
if room_type == 'bedroom' and \
stay_inside_for > 60*60 and \
now_is_sleep_time:
nxt_state = "In Sleep"
# c5. Stayed Inside -> Outside:
# (currently off for 5min) & largely off in [0,2x]
elif motion_off_for >= 5*60 and \
motion_off_ratio_for_2x_min >= 0.7:
nxt_state = "Outside"
# c6. Stayed Inside -> Stayed Inside:
# all other condition
else:
nxt_state = "Stayed Inside"
# In Sleep -> xxx
elif cur_state == 'In Sleep':
# c8. In Sleep -> Stayed Inside:
# Assuming people will wake up once it is not sleep time anymore
if not now_is_sleep_time:
nxt_state = "Stayed Inside"
# c9. In Sleep -> Outside:
# No motions for an hour and half means people are outside during sleep time
elif motion_off_for >= 90*60:
nxt_state = "Outside"
# c10. In Sleep -> In Sleep:
else:
nxt_state = "In Sleep"
# Set next state
state.set(occupancy_entity_str, nxt_state)
@service
def turn_off_gaming_pc_based_on_a_timer():
# Duration of the current gaming_pc state
from datetime import datetime as dt
from datetime import timezone as timezone
num_seconds_ago = (dt.now(tz=timezone.utc) - switch.gaming_pc.last_changed).total_seconds()
num_hours_ago = int(num_seconds_ago/3600)
# Cast of timer value
timer = int(float(input_number.gaming_pc_shutdown_timer_in_hour))
# If the gaming PC is on for more than timer value, turn off the pc
if num_hours_ago >= timer and switch.gaming_pc == 'on':
switch.gaming_pc.turn_off()