บ้านทำงานด้วย “เดี๋ยวก่อน” ไม่ใช่ “เดี๋ยวนี้”: หลับไปพร้อมพัดลม เปิดม่านตอนพระอาทิตย์ขึ้น ปิดไฟเมื่อหนังจบ ตัวจับเวลาเสียงในตัวของ Home Assistant ทำได้แค่ส่งเสียงเตือน คู่มือนี้เพิ่มการตั้งเวลาสั่งงานจริงให้ผู้ช่วยเสียง — ไฟ แอร์ หรือผ้าม่าน ห้องไหนก็ได้ ระบุเวลาหรือนับถอยหลัง เป็นภาษาอังกฤษ ไทย หรือจีนกลาง — ด้วยคอมโพเนนต์ Scheduler จากชุมชน และสคริปต์เล็ก ๆ สามตัวที่ไม่เคยอ้างเกินกว่าที่ตรวจสอบแล้ว YAML ครบชุด พร้อมปรับใช้
หนึ่งพื้นฐาน สามกริยา คอมโพเนนต์ Scheduler สร้างตารางเวลาแบบครั้งเดียวที่เรียกเซอร์วิสหนึ่งครั้งแล้วลบตัวเองได้ ส่วนที่เหลือทั้งหมดคือสคริปต์สามตัวที่โมเดลภาษาเรียกใช้ได้: ตั้งเวลา แสดงรายการ และยกเลิก แต่ละตัวคืนข้อความสำหรับพูดในภาษาที่ผู้ใช้พูดมา และผู้ช่วยถูกสั่งให้พูดตามคำต่อคำ
ตรวจก่อนพูด “ได้เลย ตอนหกโมง” ไม่มีค่าอะไรถ้าไม่มีอะไรถูกสร้างขึ้นจริง สคริปต์ตั้งเวลาจะรอสองวินาที หาเอนทิตีตารางเวลาที่เพิ่งขอสร้าง ตรวจว่าเปิดอยู่และมีเวลาทำงานครั้งถัดไปจริง แล้วจึงบอกเวลา — เวลาที่ตรวจสอบแล้ว อ่านกลับมาจากเอนทิตี ไม่ใช่เวลาที่หวังไว้ การยกเลิกก็ทำแบบเดียวกันแต่กลับด้าน: นับสิ่งที่เหลืออยู่หลังยกเลิก และยอมรับถ้ามีอะไรยังรอดอยู่
กฎอยู่ในคำอธิบายของเครื่องมือ โมเดลภาษาอ่านคำอธิบายของเครื่องมือในจังหวะที่มันกำลังตัดสินใจว่าจะใช้หรือไม่พอดี คำอธิบายจึงเป็นที่อยู่ของการจัดเส้นทาง: อย่าใช้เครื่องมือตัวจับเวลาสำหรับเรื่องนี้ แปลง “หกโมงเช้า” เป็น 06:00 ถือว่า “ไม่ต้องเปิดม่านตอนหกโมง” คือการยกเลิก ห้ามบอกว่ายกเลิกแล้วโดยไม่ได้เรียกเครื่องมือนี้ ในการทดสอบของเรา วิธีนี้น่าเชื่อถือกว่าการใส่กฎเดียวกันไว้ใน system prompt มาก
ล้มเหลวแบบปิด การผสมที่เป็นไปไม่ได้ — ผ้าม่านในห้องที่ไม่มีผ้าม่าน เวลาที่แปลความหมายไม่ได้ — จะคืนข้อความว่าไม่มีอะไรถูกตั้งเวลา โมเดลจึงแต่งความสำเร็จที่ไม่เคยได้รับมาไม่ได้
ตารางเวลาเก็บกวาดตัวเอง repeat_type: single พร้อมวันเริ่มและวันสิ้นสุดตั้งเป็นวันที่ทำงาน หมายความว่าเอนทิตีทำงานครั้งเดียวแล้วหายไป ไม่มีอะไรสะสม “มีอะไรตั้งเวลาไว้บ้าง” จึงได้คำตอบที่เป็นจริงเสมอ
scheduler.add และ scheduler.remove เท่านั้นat_time กับ in_minutes เวลาที่ผ่านไปแล้วของวันนี้จะเลื่อนไปพรุ่งนี้ การสั่งเปิดแอร์บังคับโหมดเย็น เพราะ climate.turn_on จะคืนค่าโหมดที่เครื่องจำไว้ — และโหมด “ทำความร้อน” ตอนหกโมงเช้าในกรุงเทพฯ ไม่ใช่สิ่งที่ใครขอ แก้ entity_map และตัวเลือกห้องให้ตรงกับบ้านของคุณalias: Schedule a device action (at a time or after a delay)
icon: mdi:calendar-clock
mode: queued
description: >-
Schedules a device action to happen later — either AT a clock time or IN a number of minutes. Use this
for ANY request of the form 'open/close/turn on/turn off <device> at <time>' or '... in <N> minutes/hours'
(e.g. 'open the curtains at 6 a.m. tomorrow', 'turn off the bedroom lights in 20 minutes', 'ปิดแอร์อีกครึ่งชั่วโมง').
Do NOT use the timer tool for these — a timer only chimes, it cannot perform a device action. Convert
spoken times to 24-hour HH:MM ('six a.m.' → '06:00', 'half past nine tonight' → '21:30'); if the time
has already passed today it is scheduled for tomorrow automatically. Convert durations to minutes ('an
hour' → 60). Pass exactly one of at_time or in_minutes. Returns a 'message' field in the language you
pass as 'language' — speak that message back to the user verbatim; it states the VERIFIED time the action
will run. If the message says nothing was scheduled, tell the user that.
fields:
action:
name: Action
description: 'What to do: ''open'' or ''close'' (curtains), ''turn_on'' or ''turn_off'' (lights, aircon).'
required: true
example: open
selector:
select:
options:
- open
- close
- turn_on
- turn_off
device:
name: Device
description: 'Which device class: ''curtains'', ''lights'' or ''aircon''.'
required: true
example: curtains
selector:
select:
options:
- curtains
- lights
- aircon
room:
name: Room
description: >-
The room. If the user names a room, pass it exactly as one of the options. If they don't, pass the
room the user is speaking from.
required: true
example: Living Room
selector:
select:
options:
- Living Room
- Bedroom
- Kid's Room
- Cooking Room
- Shower Room
- Bath Room
at_time:
name: At time
description: >-
Clock time to run the action, 24-hour HH:MM (e.g. '06:00', '21:30'). Use this OR in_minutes, not
both.
required: false
example: 06:00
selector:
text: null
in_minutes:
name: In minutes
description: Delay in whole minutes from now (e.g. 20, 90). Use this OR at_time, not both.
required: false
example: 20
selector:
number:
min: 1
max: 1440
mode: box
language:
name: Language
description: >-
The language the user spoke in: 'th' Thai, 'zh' Chinese, 'en' English. The message is returned in
this language. Defaults to 'en'.
required: false
example: th
selector:
select:
options:
- en
- th
- zh
sequence:
- alias: Resolve inputs
variables:
lang: '{{ language | default(''en'') }}'
act: '{{ action | default('''') }}'
dev: '{{ device | default('''') }}'
rm: '{{ room | default('''') }}'
entity_map:
curtains:
Living Room: cover.living_room_curtains
lights:
Living Room: light.living_room
Bedroom: light.bedroom
Kid's Room: light.kids_room
Cooking Room: light.cooking_room
Shower Room: light.shower_room
Bath Room: light.bath_room
aircon:
Living Room: climate.living_room
Bedroom: climate.bedroom
Kid's Room: climate.kids_room
target_entity: '{{ entity_map.get(dev, {}).get(rm, '''') }}'
svc: >-
{% if dev == 'curtains' and act == 'open' %}cover.open_cover{% elif dev == 'curtains' and act ==
'close' %}cover.close_cover{% elif dev == 'lights' and act in ['turn_on','open'] %}light.turn_on{%
elif dev == 'lights' and act in ['turn_off','close'] %}light.turn_off{% elif dev == 'aircon' and
act in ['turn_on','open'] %}climate.set_hvac_mode{% elif dev == 'aircon' and act in ['turn_off','close']
%}climate.set_hvac_mode{% else %}{% endif %}
svc_data: >-
{% if dev == 'aircon' and act in ['turn_on','open'] %}{{ {'hvac_mode': 'cool'} }}{% elif dev ==
'aircon' and act in ['turn_off','close'] %}{{ {'hvac_mode': 'off'} }}{% else %}{{ {} }}{% endif
%}
has_delay: '{{ in_minutes is defined and in_minutes is not none and (in_minutes | int(0)) > 0 }}'
has_time: >-
{{ at_time is defined and at_time is not none and (at_time | string) is match('^([01]?\d|2[0-3]):[0-5]\d$')
}}
fire_at: >-
{% set n = now() %}{% if in_minutes is defined and in_minutes is not none and (in_minutes | int(0))
> 0 %}{{ (n + timedelta(minutes=(in_minutes | int))).isoformat() }}{% elif at_time is defined and
at_time is not none and (at_time | string) is match('^([01]?\d|2[0-3]):[0-5]\d$') %}{% set hh =
(at_time | string).split(':')[0] | int %}{% set mm = (at_time | string).split(':')[1] | int %}{%
set t = n.replace(hour=hh, minute=mm, second=0, microsecond=0) %}{% if t <= n %}{% set t = t + timedelta(days=1)
%}{% endif %}{{ t.isoformat() }}{% else %}{{ '' }}{% endif %}
- alias: Validate
choose:
- conditions:
- condition: template
value_template: '{{ target_entity == '''' or svc == '''' or fire_at == '''' }}'
sequence:
- variables:
message: >-
{% if lang == 'th' %}ขอโทษค่ะ ตั้งเวลาไม่ได้ ไม่ได้ตั้งอะไรไว้เลย{% elif lang == 'zh' %}抱歉,无法设置定时,什么也没有安排。{%
else %}Sorry — I couldn't set that schedule. Nothing was scheduled.{% endif %}
reason: target={{ target_entity }} svc={{ svc }} fire_at={{ fire_at }}
- variables:
result_vars:
message: '{{ message }}'
scheduled: false
reason: '{{ reason }}'
- stop: invalid request
response_variable: result_vars
- alias: Compute names and times
variables:
fire_dt: '{{ as_datetime(fire_at) }}'
fire_date: '{{ as_datetime(fire_at).strftime(''%Y-%m-%d'') }}'
fire_hhmm: '{{ as_datetime(fire_at).strftime(''%H:%M'') }}'
is_tomorrow: '{{ as_datetime(fire_at).date() != now().date() }}'
sched_name: >-
Voice: {{ act }} {{ rm }} {{ dev }} @ {{ as_datetime(fire_at).strftime('%d/%m %H:%M') }} [{{ now().strftime('%H%M%S')
}}]
- alias: Create the schedule
action: scheduler.add
continue_on_error: true
data:
name: '{{ sched_name }}'
weekdays:
- daily
start_date: '{{ fire_date }}'
end_date: '{{ fire_date }}'
repeat_type: single
timeslots:
- start: '{{ fire_hhmm }}'
actions:
- service: '{{ svc }}'
entity_id: '{{ target_entity }}'
service_data: '{{ svc_data }}'
- delay:
seconds: 2
- alias: Verify the schedule entity exists
variables:
sched_entity: >-
{{ states.switch | selectattr('attributes.friendly_name', 'eq', 'Scheduler ' ~ sched_name) | map(attribute='entity_id')
| list | first | default('') }}
sched_ok: >-
{{ sched_entity != '' and is_state(sched_entity, 'on') and state_attr(sched_entity, 'next_trigger')
is not none }}
- alias: Build the spoken message
variables:
room_th: >-
{{ {'Living Room': 'ห้องนั่งเล่น', 'Bedroom': 'ห้องนอน', "Kid's Room": 'ห้องเด็ก', 'Cooking Room':
'ห้องครัว', 'Shower Room': 'ห้องอาบน้ำ', 'Bath Room': 'ห้องน้ำ'}.get(rm, rm) }}
room_zh: >-
{{ {'Living Room': '客厅', 'Bedroom': '卧室', "Kid's Room": '孩子的房间', 'Cooking Room': '厨房', 'Shower Room':
'淋浴间', 'Bath Room': '浴室'}.get(rm, rm) }}
dev_en: '{{ {''curtains'': ''curtains'', ''lights'': ''lights'', ''aircon'': ''aircon''}.get(dev,
dev) }}'
dev_th: '{{ {''curtains'': ''ม่าน'', ''lights'': ''ไฟ'', ''aircon'': ''แอร์''}.get(dev, dev) }}'
dev_zh: '{{ {''curtains'': ''窗帘'', ''lights'': ''灯'', ''aircon'': ''空调''}.get(dev, dev) }}'
verb_en: >-
{{ {'open': 'open', 'close': 'close', 'turn_on': 'turn on', 'turn_off': 'turn off'}.get(act, act)
}}
verb_th: '{{ {''open'': ''เปิด'', ''close'': ''ปิด'', ''turn_on'': ''เปิด'', ''turn_off'': ''ปิด''}.get(act,
act) }}'
verb_zh: '{{ {''open'': ''打开'', ''close'': ''关闭'', ''turn_on'': ''打开'', ''turn_off'': ''关闭''}.get(act,
act) }}'
when_en: >-
{% if has_delay %}in {{ in_minutes | int }} minutes, at {{ fire_hhmm }}{% else %}at {{ fire_hhmm
}}{% if is_tomorrow %} tomorrow{% endif %}{% endif %}
when_th: >-
{% if has_delay %}อีก {{ in_minutes | int }} นาที เวลา {{ fire_hhmm }} น.{% else %}เวลา {{ fire_hhmm
}} น.{% if is_tomorrow %} พรุ่งนี้{% endif %}{% endif %}
when_zh: >-
{% if has_delay %}{{ in_minutes | int }}分钟后,{{ fire_hhmm }}{% else %}{% if is_tomorrow %}明天{% endif
%}{{ fire_hhmm }}{% endif %}
message: >-
{% if sched_ok %}{% if lang == 'th' %}จะ{{ verb_th }}{{ dev_th }}{{ room_th }}{{ when_th }}ค่ะ{%
elif lang == 'zh' %}将于{{ when_zh }}{{ verb_zh }}{{ room_zh }}{{ dev_zh }}。{% else %}I'll {{ verb_en
}} the {{ rm | lower }} {{ dev_en }} {{ when_en }}.{% endif %}{% else %}{% if lang == 'th' %}ขอโทษค่ะ
ตั้งเวลาไม่ได้ ไม่ได้ตั้งอะไรไว้เลย{% elif lang == 'zh' %}抱歉,无法设置定时,什么也没有安排。{% else %}Sorry — I
couldn't set that schedule. Nothing was scheduled.{% endif %}{% endif %}
result_vars:
message: '{{ message }}'
scheduled: '{{ sched_ok }}'
schedule_entity: '{{ sched_entity }}'
fires_at: '{{ fire_at }}'
target: '{{ target_entity }}'
service: '{{ svc }}'
- alias: Return
stop: done
response_variable: result_varsVoice: … — แล้วรายงานเรียงตามเวลาทำงาน พร้อม “อีก 7 ชั่วโมง 28 นาที” ที่ตรวจสอบแล้วในแต่ละรายการ โมเดลจึงไม่ต้องคิดเลขเองalias: List scheduled actions
icon: mdi:calendar-search
mode: queued
description: >-
Reports pending scheduled device actions (set with schedule_action: 'at <time>' or 'in <N> minutes').
Use this whenever the user asks what is scheduled, what timers/schedules are set, WHEN something will
happen, or HOW LONG UNTIL something happens ('when will the curtains open', 'how long until the aircon
turns off', 'อีกนานแค่ไหนม่านจะเปิด', '还有多久窗帘会打开'). Do NOT use the built-in timer status — it only knows
chime timers. If the user names a device or room, pass it as a filter so the answer is about that device
only. ALWAYS call this tool before answering, even if you answered a similar question earlier in this
conversation — schedules change and only this tool knows the current state. Returns 'message' in the
language you pass as 'language'; speak it verbatim. Each item carries 'relative' (verified time remaining,
e.g. 'in 7 hours 28 minutes') — read it out for 'how long until' questions, never calculate it yourself.
If the message says nothing is scheduled for the device, say exactly that.
fields:
language:
name: Language
description: 'The language the user spoke in: ''th'' Thai, ''zh'' Chinese, ''en'' English. Defaults
to ''en''.'
required: false
example: th
selector:
select:
options:
- en
- th
- zh
device:
name: Device
description: >-
Optional filter: 'curtains', 'lights' or 'aircon'. Pass it when the user asks about a specific device.
required: false
example: curtains
selector:
select:
options:
- curtains
- lights
- aircon
room:
name: Room
description: 'Optional filter: the room, exactly as one of the options.'
required: false
example: Living Room
selector:
select:
options:
- Living Room
- Bedroom
- Kid's Room
- Cooking Room
- Shower Room
- Bath Room
sequence:
- variables:
lang: '{{ language | default(''en'') }}'
dev: '{{ device | default('''') }}'
rm: '{{ room | default('''') }}'
items: >-
{% set ns = namespace(rows=[]) %}{% for s in states.switch if s.entity_id.startswith('switch.schedule_voice')
and s.state == 'on' and s.attributes.next_trigger is not none %}{% set fn = s.attributes.friendly_name
| replace('Scheduler Voice: ', '') %}{% set parts = fn.split(' @ ')[0].split(' ') %}{% if (not dev
or dev == parts[-1]) and (not rm or rm == (parts[1:-1] | join(' '))) %}{% set ns.rows = ns.rows
+ [{'entity': s.entity_id, 'action': parts[0], 'room': parts[1:-1] | join(' '), 'device': parts[-1],
'at': s.attributes.next_trigger | string}] %}{% endif %}{% endfor %}{{ ns.rows | sort(attribute='at')
}}
count: '{{ items | count }}'
- variables:
room_th:
Living Room: ห้องนั่งเล่น
Bedroom: ห้องนอน
Kid's Room: ห้องเด็ก
Cooking Room: ห้องครัว
Shower Room: ห้องอาบน้ำ
Bath Room: ห้องน้ำ
room_zh:
Living Room: 客厅
Bedroom: 卧室
Kid's Room: 孩子的房间
Cooking Room: 厨房
Shower Room: 淋浴间
Bath Room: 浴室
dev_th:
curtains: ม่าน
lights: ไฟ
aircon: แอร์
dev_zh:
curtains: 窗帘
lights: 灯
aircon: 空调
verb_en:
open: open
close: close
turn_on: turn on
turn_off: turn off
verb_th:
open: เปิด
close: ปิด
turn_on: เปิด
turn_off: ปิด
verb_zh:
open: 打开
close: 关闭
turn_on: 打开
turn_off: 关闭
- variables:
dev_lbl_en: >-
{% if dev and rm %}the {{ rm | lower }} {{ dev }}{% elif dev %}the {{ dev }}{% elif rm %}the {{
rm | lower }}{% else %}{% endif %}
dev_lbl_th: >-
{% set d = {'curtains': 'ม่าน', 'lights': 'ไฟ', 'aircon': 'แอร์'}.get(dev, '') %}{% set r = {'Living
Room': 'ห้องนั่งเล่น', 'Bedroom': 'ห้องนอน', "Kid's Room": 'ห้องเด็ก', 'Cooking Room': 'ห้องครัว',
'Shower Room': 'ห้องอาบน้ำ', 'Bath Room': 'ห้องน้ำ'}.get(rm, '') %}{{ d ~ r }}
dev_lbl_zh: >-
{% set d = {'curtains': '窗帘', 'lights': '灯', 'aircon': '空调'}.get(dev, '') %}{% set r = {'Living
Room': '客厅', 'Bedroom': '卧室', "Kid's Room": '孩子的房间', 'Cooking Room': '厨房', 'Shower Room': '淋浴间',
'Bath Room': '浴室'}.get(rm, '') %}{{ r ~ d }}
message: >-
{% if count | int == 0 %}{% if lang == 'th' %}{% if dev_lbl_th %}ไม่มีรายการตั้งเวลาสำหรับ{{ dev_lbl_th
}}ค่ะ{% else %}ไม่มีรายการตั้งเวลาค่ะ{% endif %}{% elif lang == 'zh' %}{% if dev_lbl_zh %}{{ dev_lbl_zh
}}没有任何定时安排。{% else %}没有任何定时安排。{% endif %}{% else %}{% if dev_lbl_en %}Nothing is scheduled for {{
dev_lbl_en }}.{% else %}Nothing is scheduled.{% endif %}{% endif %}{% else %}{% set ns = namespace(txt=[])
%}{% for r in items %}{% set secs = ((as_datetime(r.at) - now()).total_seconds()) | int %}{% set
h = secs // 3600 %}{% set m = (secs % 3600) // 60 %}{% set rel = ('in ' ~ (h ~ ' hour' ~ ('s' if
h != 1 else '') ~ ' ' if h > 0 else '') ~ (m ~ ' minute' ~ ('s' if m != 1 else '') if (m > 0 or
h == 0) else '')) | trim %}{% set rel_th = ('อีก ' ~ (h ~ ' ชั่วโมง ' if h > 0 else '') ~ (m ~ '
นาที' if (m > 0 or h == 0) else '')) | trim %}{% set rel_zh = ((h ~ '小时' if h > 0 else '') ~ (m
~ '分钟' if (m > 0 or h == 0) else '') ~ '后') %}{% set day = '' if as_datetime(r.at).date() == now().date()
else (' พรุ่งนี้' if lang == 'th' else ('明天' if lang == 'zh' else ' tomorrow')) %}{% if lang ==
'th' %}{% set ns.txt = ns.txt + [verb_th.get(r.action, r.action) ~ dev_th.get(r.device, r.device)
~ room_th.get(r.room, r.room) ~ ' เวลา ' ~ as_datetime(r.at).strftime('%H:%M') ~ ' น.' ~ day ~ '
(' ~ rel_th ~ ')'] %}{% elif lang == 'zh' %}{% set ns.txt = ns.txt + [day ~ as_datetime(r.at).strftime('%H:%M')
~ verb_zh.get(r.action, r.action) ~ room_zh.get(r.room, r.room) ~ dev_zh.get(r.device, r.device)
~ '(' ~ rel_zh ~ ')'] %}{% else %}{% set ns.txt = ns.txt + [verb_en.get(r.action, r.action) ~ '
the ' ~ (r.room | lower) ~ ' ' ~ r.device ~ ' at ' ~ as_datetime(r.at).strftime('%H:%M') ~ day ~
' (' ~ rel ~ ')'] %}{% endif %}{% endfor %}{% if lang == 'th' %}มี {{ count }} รายการค่ะ: {{ ns.txt
| join(', ') }}{% elif lang == 'zh' %}共有{{ count }}项安排:{{ ns.txt | join(';') }}。{% else %}{{ count
}} scheduled: {{ ns.txt | join('; ') }}.{% endif %}{% endif %}
result_vars:
message: '{{ message }}'
count: '{{ count }}'
items: >-
{% set ns = namespace(l=[]) %}{% for r in items %}{% set secs = ((as_datetime(r.at) - now()).total_seconds())
| int %}{% set h = secs // 3600 %}{% set m = (secs % 3600) // 60 %}{% set rel = ('in ' ~ (h ~
' hour' ~ ('s' if h != 1 else '') ~ ' ' if h > 0 else '') ~ (m ~ ' minute' ~ ('s' if m != 1 else
'') if (m > 0 or h == 0) else '')) | trim %}{% set ns.l = ns.l + [{'entity': r.entity, 'action':
r.action, 'room': r.room, 'device': r.device, 'at': r.at, 'relative': rel, 'minutes_until': secs
// 60}] %}{% endfor %}{{ ns.l }}
- stop: done
response_variable: result_varsalias: Cancel scheduled actions
icon: mdi:calendar-remove
mode: queued
description: >-
Cancels pending scheduled device actions that were set with schedule_action. Use this for ANY request
to undo, stop or prevent a scheduled action, however it is phrased: 'cancel the curtain schedule', 'don't
open the curtains at six', 'never mind the aircon later', 'stop the lights turning off', 'the curtains
have been cancelled' (treat a statement that something is cancelled as a request to cancel it), 'ยกเลิกที่ตั้งเวลาไว้',
'อย่าเปิดม่านตอนหกโมง', '取消窗帘的定时'. Never reply that something is cancelled or will not happen without
calling this tool — only its message is the truth. Filter by device and/or room if the user names them;
pass nothing to cancel ALL scheduled actions (confirm first if more than one would be cancelled and
they didn't say 'all'). Returns a 'message' field in the language you pass as 'language' — speak it
back verbatim.
fields:
device:
name: Device
description: 'Optional filter: ''curtains'', ''lights'' or ''aircon''.'
required: false
example: curtains
selector:
select:
options:
- curtains
- lights
- aircon
room:
name: Room
description: 'Optional filter: the room, exactly as one of the options.'
required: false
example: Living Room
selector:
select:
options:
- Living Room
- Bedroom
- Kid's Room
- Cooking Room
- Shower Room
- Bath Room
language:
name: Language
description: 'The language the user spoke in: ''th'', ''zh'' or ''en''. Defaults to ''en''.'
required: false
example: th
selector:
select:
options:
- en
- th
- zh
sequence:
- variables:
lang: '{{ language | default(''en'') }}'
dev: '{{ device | default('''') }}'
rm: '{{ room | default('''') }}'
targets: >-
{% set ns = namespace(l=[]) %}{% for s in states.switch if s.entity_id.startswith('switch.schedule_voice')
%}{% set fn = s.attributes.friendly_name | replace('Scheduler Voice: ', '') %}{% set parts = fn.split('
@ ')[0].split(' ') %}{% set r_room = parts[1:-1] | join(' ') %}{% set r_dev = parts[-1] %}{% if
(dev == '' or dev == r_dev) and (rm == '' or rm == r_room) %}{% set ns.l = ns.l + [s.entity_id]
%}{% endif %}{% endfor %}{{ ns.l }}
n: '{{ targets | count }}'
- repeat:
for_each: '{{ targets }}'
sequence:
- action: scheduler.remove
continue_on_error: true
data:
entity_id: '{{ repeat.item }}'
- delay:
seconds: 1
- variables:
left: '{{ states.switch | selectattr(''entity_id'', ''in'', targets) | list | count }}'
message: >-
{% if n | int == 0 %}{% if lang == 'th' %}ไม่มีรายการตั้งเวลาที่ตรงกันค่ะ{% elif lang == 'zh' %}没有匹配的定时安排。{%
else %}There was nothing scheduled that matches.{% endif %}{% elif left | int == 0 %}{% if lang
== 'th' %}ยกเลิกแล้ว {{ n }} รายการค่ะ{% elif lang == 'zh' %}已取消{{ n }}项安排。{% else %}Cancelled {{
n }} scheduled action{{ 's' if n | int > 1 else '' }}.{% endif %}{% else %}{% if lang == 'th' %}ขอโทษค่ะ
ยกเลิกไม่สำเร็จ ยัง{{ left }}รายการค้างอยู่{% elif lang == 'zh' %}抱歉,取消失败,仍有{{ left }}项未取消。{% else
%}Sorry — {{ left }} of {{ n }} could not be cancelled and are still scheduled.{% endif %}{% endif
%}
result_vars:
message: '{{ message }}'
cancelled: '{{ (n | int) - (left | int) }}'
remaining: '{{ left }}'
- stop: done
response_variable: result_vars