-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathautomatic-room-occupancy.yaml
247 lines (247 loc) · 9.1 KB
/
automatic-room-occupancy.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
blueprint:
name: "[Occupancy] Auto Room Occupancy"
description:
"Automatically turn on and off an ocupancy switch for a single room.\n
\n------LOGIC------\nOccupied when ANY of the following conditions are met (all are\
\ optional).\n - door is shut\n - any motion\n - any media player playing\n\
\ - door is shut (for rooms eg bathrooms)\n - on room presence (eg room-assistant)\n\
\nOccupancy is cleared when ALL of the following conditions are met (all are\
\ optional):\n - motion off for a set amount of time\n - no player in room played\
\ for a set amount of time\n - no one in room\n\n------HELPERS------\n\
\ Uses the following helpers to allow for front end control of timeouts:\n\
\ - input_number.door_occupancy_timeout (default: 0 mins)\n\
\ - input_number.motion_occupancy_timeout (default: 10 mins)\n\
\ - input_number.media_occupancy_timeout (default: 10 mins)\n\
\ - input_number.bluetooth_occupancy_timeout (default: 10 mins)\
\ (NOT IN USE YET)\n\
\ - input_boolean.guest (on if guest is at home)\n\
\ - group.household (group of all person entities in household)"
domain: automation
input:
occupied_on_motion_enabled:
name: Enable Motion Occupancy
description: Turn on/off occupancy via motion sensor(s).
default: true
selector:
boolean:
motion_sensor:
name: Motion Sensor(s)
description: Motion sensor (or group of motion sensors) in the room.
default: binary_sensor.none
selector:
entity:
domain: binary_sensor
device_class: motion
occupied_on_shut_door:
name: Enable Door Occupancy
description: Turn on/off occupancy via door sensor(s).
default: false
selector:
boolean:
door_sensor:
name: Door Sensor(s)
description: Door sensor (or group of door sensors) for the room.
default: binary_sensor.none
selector:
entity:
domain: binary_sensor
device_class: opening
occupied_on_media_enabled:
name: Enable Media Occupancy
description: Turn on/off occupancy via media player(s).
default: false
selector:
boolean:
media_players:
name: Media Player(s)
description: List of media player entities in room (comma separated).
default: media_player.none
selector:
entity:
domain: media_player
media_states:
name: Media State(s)
description: Media player state(s) when room is occupied (comma separated).
default: playing
selector:
text:
occupied_on_presence_enabled:
name: Enable Presence Occupancy
description: Turn on/off occupancy via presence sensor(s).
default: false
selector:
boolean:
presence_entities:
name: Presence Entity or Entities
description: Room presence entity or entities (comma separated) to track.
default: sensor.none
selector:
text:
presence_states:
name: Presence State(s)
description: A comma separated list of states that presence entity can match.
default: lounge, dining room
selector:
text:
disabled_entity_id:
name: Disable Mode (Optional)
description: An input_boolean to disable automation logic when on.
default: none
selector:
entity:
domain: input_boolean
household_group:
name: Household Group (Optional)
description: A grouped set of people in your house. Logic will only run if home.
default: group.household
selector:
entity:
domain: group
guest_mode_switch:
name: Guest Mode (Optional)
description: An input_boolean to allow logic to work when household group is away.
default: input_boolean.guest
selector:
entity:
domain: input_boolean
occupancy_switch:
name: Occupancy Switch
description:
An input_boolean that switches occupancy state in target room.
On = occupied and Off = not_occupied.
default: none
selector:
entity:
domain: input_boolean
source_url: https://github.com/kreene1987/automatic-room-occupancy/blob/main/automatic-room-occupancy.yaml
variables:
time_now: "{{ as_timestamp(now()) }}"
media_players_str: !input "media_players"
media_players: "{{ media_players_str.split(',') | map('trim') | list }}"
media_states_str: !input "media_states"
media_states: "{{ media_states_str.split(',') | map('trim') | list }}"
media_timeout: "{{ states('input_number.media_occupancy_timeout') | int(10) }}"
media_is_playing:
"{{ expand(media_players) | selectattr('state','in', media_states)
| list | count > 0 }}"
presence_entities_str: !input "presence_entities"
presence_entities: "{{ presence_entities_str.split(',') | map('trim') | list
}}"
presence_states_str: !input "presence_states"
presence_states: "{{ presence_states_str.split(',') | map('trim') | list }}"
presence_timeout:
"{{ states('input_number.bluetooth_occupancy_timeout') | int(10)
}}"
in_room:
"{{ expand(presence_entities) | selectattr('state','in', presence_states)
| list | count > 0 }}"
motion_sensor: !input "motion_sensor"
motion_timeout:
"{{ states('input_number.motion_occupancy_timeout') | float(10)
}}"
motion_last_changed:
"{{ states[motion_sensor].last_changed.timestamp() | float(0)
}}"
motion_is_timed_out:
"{{ (time_now - motion_last_changed) > (motion_timeout * 60)
}}"
is_motion: "{{ is_state(motion_sensor, 'on') }}"
door_sensor: !input "door_sensor"
door_shut: "{{ is_state(door_sensor, 'off') }}"
occupied_on_motion_enabled: !input "occupied_on_motion_enabled"
occupied_on_shut_door_enabled: !input "occupied_on_shut_door"
occupied_on_media_enabled: !input "occupied_on_media_enabled"
occupied_on_presence_enabled: !input "occupied_on_presence_enabled"
disabled_entity_id: !input "disabled_entity_id"
blueprint_disabled:
"{{ disabled_entity_id != 'none' and is_state(disabled_entity_id,
'on') }}"
household_group: !input "household_group"
guest_mode_switch: !input "guest_mode_switch"
house_home: "{{ household_group == 'none' or is_state(household_group, 'home')
}}"
guests_home:
"{{ guest_mode_switch == 'none' or is_state(guest_mode_switch, 'on')
}}"
at_home: "{{ house_home or guests_home }}"
mode: parallel
trigger:
- platform: state
entity_id: !input "door_sensor"
to: "off"
- platform: state
entity_id: !input "door_sensor"
to: "on"
for:
minutes: "{{ states('input_number.door_occupancy_timeout') | int(0) }}"
- platform: state
entity_id: !input "motion_sensor"
to: "on"
- platform: state
entity_id: !input "motion_sensor"
to: "off"
for:
minutes: "{{ states('input_number.motion_occupancy_timeout') | int(10) }}"
- platform: state
entity_id: !input "media_players"
- platform: state
entity_id: !input "presence_entities"
from:
condition:
- "{{ not blueprint_disabled }}"
action:
- choose:
- conditions:
- "{{ occupied_on_shut_door_enabled }}"
- "{{ door_shut }}"
- "{{ at_home }}"
sequence:
- service: input_boolean.turn_on
data:
entity_id: !input "occupancy_switch"
- conditions:
- "{{ occupied_on_motion_enabled }}"
- "{{ is_motion }}"
- "{{ at_home }}"
sequence:
- service: input_boolean.turn_on
data:
entity_id: !input "occupancy_switch"
- conditions:
- "{{ occupied_on_media_enabled }}"
- "{{ media_is_playing }}"
- "{{ at_home }}"
sequence:
- service: input_boolean.turn_on
data:
entity_id: !input "occupancy_switch"
- conditions:
- "{{ occupied_on_presence_enabled }}"
- "{{ in_room }}"
- "{{ at_home }}"
sequence:
- service: input_boolean.turn_on
data:
entity_id: !input "occupancy_switch"
- conditions:
- "{{ not at_home }}"
sequence:
- service: input_boolean.turn_off
data:
entity_id: !input "occupancy_switch"
- conditions:
- "{{ not is_motion }}"
- "{{ motion_is_timed_out }}"
- "{% set t = (time_now - media_timeout) * 60 %} {% set ns = namespace(not_playing=[])\
\ %} {% for player in media_players %}\n {% for state in media_states %}\n\
\ {% if states[player].last_changed is defined %}\n {% set timed_out\
\ = states[player].last_changed.timestamp() < t %}\n {% else %}\n {%\
\ set timed_out = true %}\n {% endif %}\n {% if states(player) != state\
\ and timed_out %}\n {% set ns.not_playing = ns.not_playing + [ player.entity_id\
\ ] %}\n {% endif %}\n {% endfor %}\n{% endfor %} {{ ns.not_playing | length\
\ >= media_players | length }}\n"
- "{{ not in_room }}"
sequence:
- service: input_boolean.turn_off
data:
entity_id: !input "occupancy_switch"