Install
openclaw skills install when-clock-skillControl WHEN/WHEN Voice LAN clock devices. Supports voice time announcement, weather broadcast (WHEN Voice only), alarm CRUD, and countdown timer. Use --device-id to specify device.
openclaw skills install when-clock-skillwhen-clock-skill.pyconfig.json in script directory (fill devices array with id and clock_ip)python when-clock-skill.py --mode <mode> --device-id <device_id> [options...]
--device-iddefaults todefault(for backward compatibility with single-device config).
| Mode | Description | Required Args | Device Support |
|---|---|---|---|
chime | Voice time announcement | — | WHEN Voice only |
weather | Voice weather broadcast | — | WHEN Voice only |
get_alarm | Query all alarms | — | Both |
set_alarm | Add new alarm | --alarm-time | Both |
edit_alarm | Modify alarm (partial update) | --alarm-index | Both |
delete_alarm | Delete alarm | --alarm-index | Both |
set_timer | Countdown timer (single alarm) | --timer-offset | Both |
Announces current time. WHEN devices do not support this mode.
python when-clock-skill.py --mode chime --device-id device1
python when-clock-skill.py --mode chime --device-id device1 --volume 20
Optional: --volume 1~30 (uses device current volume if not specified)
Output:
{"ok": true, "mode": "chime", "action": "voice_announce_preview", "result": "success", "status": 0, "message": "succ"}
WHEN devices do not support this mode.
Note: Weather broadcast currently only supports China region. More regions will be added in future updates.
python when-clock-skill.py --mode weather --device-id device1
python when-clock-skill.py --mode weather --device-id device1 --volume 20
Output:
{"ok": true, "mode": "weather", "action": "voice_weather_preview", "result": "success", "status": 0, "message": "succ"}
python when-clock-skill.py --mode get_alarm --device-id device1
WHEN device alarm entries do not include
volumefield.
WHEN Voice output example (with volume):
{
"ok": true,
"mode": "get_alarm",
"alarm_count": 2,
"alarms": [
{"index": 1, "mode": "Workday", "time": "07:30:00", "ring": "Reveille", "ring_duration_level": "2min", "volume": 20},
{"index": 2, "mode": "Weekly", "time": "09:00:00", "ring": "Weather(1x)", "ring_duration_level": "30S", "volume": 15, "active_days": ["Mon", "Wed"]}
]
}
alarms[].indexis the--alarm-indexvalue needed byedit_alarm/delete_alarm.
# Once (default)
python when-clock-skill.py --mode set_alarm --device-id device1 --alarm-time 07:30
# Workdays
python when-clock-skill.py --mode set_alarm --device-id device1 --alarm-mode workday --alarm-time 08:00
# Weekly on specific days
python when-clock-skill.py --mode set_alarm --device-id device1 --alarm-mode weekly --alarm-week 1,2,3,4,5 --alarm-time 08:10
# WHEN Voice - full params
python when-clock-skill.py --mode set_alarm --device-id device1 --alarm-time 07:30 --alarm-ring 5 --alarm-delay 6 --alarm-volume 20
# WHEN - ring only 1-6
python when-clock-skill.py --mode set_alarm --device-id device1 --alarm-time 07:30 --alarm-ring 3
Optional params (use config.json alarm_defaults if not specified):
--alarm-mode: once/weekly/workday/restday/off, default once--alarm-week: required for weekly, e.g. 1,2,3,4,5 or Mon,Wed,Fri--alarm-ring: ring ID (WHEN Voice: 1--alarm-delay: duration level (0-based, 0~11)--alarm-volume: volume 1~30 (WHEN Voice only)Maximum 10 alarms per device.
Output:
{"ok": true, "mode": "set_alarm", "action": "add_alarm", "result": "success", "status": 0, "message": "succ", "alarm_count": 3, "added_alarm": {"mode": "Once", "time": "07:30:00", "ring": "Reveille", "ring_duration_level": "2min", "volume": 20, "active_days": []}}
Only specified fields are updated; other fields keep original values.
# Change time only
python when-clock-skill.py --mode edit_alarm --device-id device1 --alarm-index 1 --alarm-time 07:45
# Change time and volume (WHEN Voice)
python when-clock-skill.py --mode edit_alarm --device-id device1 --alarm-index 2 --alarm-time 08:30 --alarm-volume 25
# Change to workday mode
python when-clock-skill.py --mode edit_alarm --device-id device1 --alarm-index 1 --alarm-mode workday
--alarm-index is required (use get_alarm to check indices first).
Output:
{"ok": true, "mode": "edit_alarm", "action": "update_alarm", "result": "success", "status": 0, "message": "succ", "alarm_count": 3, "updated_alarm": {"index": 1, "mode": "Once", "time": "07:45:00", "ring": "Reveille", "ring_duration_level": "2min", "volume": 20, "active_days": []}}
python when-clock-skill.py --mode delete_alarm --device-id device1 --alarm-index 2
--alarm-index is required.
Output:
{"ok": true, "mode": "delete_alarm", "action": "remove_alarm", "result": "success", "status": 0, "message": "succ", "alarm_count": 2, "removed_alarm": {"index": 2, "mode": "Once", "time": "09:00:00", "ring": "Weather(1x)", "ring_duration_level": "30S", "volume": 15, "active_days": []}}
Takes current local time + offset, writes as a single-shot alarm to device.
# 5 minutes later (uses config default ring/volume)
python when-clock-skill.py --mode set_timer --device-id device1 --timer-offset 5m
# 1 hour 30 minutes later
python when-clock-skill.py --mode set_timer --device-id device1 --timer-offset 1h30m
# 90 seconds, custom ring and volume (WHEN Voice)
python when-clock-skill.py --mode set_timer --device-id device1 --timer-offset 90s --alarm-ring 5 --alarm-volume 20
--timer-offset format: 5m, 1h, 1h30m, 90s, 1h30m20s. Plain number treated as minutes.
Output:
{"ok": true, "mode": "set_timer", "action": "add_timer", "result": "success", "status": 0, "message": "succ", "alarm_count": 3, "timer": {"offset": "5m", "offset_seconds": 300, "trigger_at": "14:35:00", "ring": "Reveille", "ring_duration_level": "2min", "volume": 20}}
| ID | Name | ID | Name |
|---|---|---|---|
| 1 | Weather(1x) | 2 | Weather(2x) |
| 3 | Weather(3x) | 4 | Beep-1 |
| 5 | Reveille | 6 | Rest Call |
| 43 | Morning | 44 | Evening |
| 49 | Chinese-style music-1 | 50 | Chinese-style music-2 |
| ID | Name |
|---|---|
| 1 | beep1 |
| 2 | beep2 |
| 3 | beep3 |
| 4 | beep4 |
| 5 | beep5 |
| 6 | beep6 |
Full WHEN Voice list in
config.jsonalarm_defaults_note.ring_id_name.
--alarm-index) is 1-based, starting from 1--alarm-ring) is 1-based, internally converted to device 0-based1~30, sent as volume-1 (WHEN Voice only)config.json devices array must have valid id and clock_ip, or script exits with code 2ok == true, fallback to status == 0stderr, normal JSON to stdout| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Device returned failure status |
| 2 | Argument / config / response format error |
| 3 | HTTP error |
| 4 | Network error |