says ⮞ I use 20x magnification when I code and debug. I use emoji to simplify logs for myself. If you can't handle my code style you can disable most of it on this website by toggling the button in the navbar. Shall duck continue?
You can have a lot of fun here for sure.
Let the qwackin' begin!
Action Types Supported
All automations can execute actions.
There are four different types of actions that can be executed. 1. Shell Commands
⮞ View Shell Commands Action Type Example
{
type = "shell";
command = "echo 'Hello World'";
}
{
type = "shell";
command = "echo 'Hello World'";
}
{
type = "scene";
scene = "movie_time";
}
{
type = "scene";
scene = "movie_time";
}
4. Simple String (legacy)
⮞ View Simple String Action Type Example
"echo 'Hello Ducks'"
"echo 'Hello Ducks'"
Dark Time
It might be one of the most important automation. Short and boring - but important.
Define when motion sensors should trigger lights, and for how long they should be turned on.
⮞ View `config.house.darkTime` code block
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
darkTime = {
enable = true;
after = "14"; # 🦆 duck say ⮞ 2 PM
before = "9"; # 🦆 duck say ⮞ 9 AM
duration = "900"; # 🦆 duck say ⮞ defined in seconds, before turning off again
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
darkTime = {
enable = true;
after = "14";
before = "9";
duration = "900";
};
};}
Greeting
When no motion has been detected in your house for x seconds - welcome you home with a greeting!
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
greeting = {
enable = true;
awayDuration = "7200"; # 🦆 duck say ⮞ how many seconds away before trigger
greeting = "Welcome back! Starting the party!"; # 🦆 duck say ⮞ greeting message that will be spoken over TTS
delay = "10"; # 🦆 duck say ⮞ time in seconds before calling the greeting
sayOnHost = "desktop"; # 🦆 duck say ⮞ on what host to play the TTS
action = {
type = "shell"; # 🦆 duck say ⮞ or "mqtt" or "scene"
command = ''
# 🦆 duck say ⮞ imagination is the key
'';
};
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
greeting = {
enable = true;
awayDuration = "7200";
greeting = "Welcome back! Starting the party!";
sayOnHost = "desktop";
delay = "5";
action = {
type = "shell";
command = ''
...
'';
};
};
};
};
};}
⮞ simple huh? - i enjoy this auto a lot qwack
Automation Types
There are currently six different automation types:
Dimmer Action Automations
Configure your dimmers.
This is optional, as they have default action's pre-configured in zigduck-rs (next page).
Default actions are: on_press_release: Turn on all zigbee devices with type 'light' in the dimmers room at last known state. on_hold_release: Turn on all zigbee devices with type 'light' at maximum brightness. up_press_release: Increase brightness of all zigbee devices with type 'light' in dimmers room. up_hold_release: None. down_press_release: Decrease brightness of all zigbee devices with type 'light' in dimmers room. down_hold_release: None. off_press_release: Turn off all zigbee devices with type 'light' in dimmer's room. off_hold_release: Turn off all zigbee devices with type 'light'.
This is an example snippet of how a dimmer override automation may look:
⮞ View `config.house.zigbee.automations.dimmer_actions` code example
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
dimmer_actions = {
livingroom = { # 🦆 duck say ⮞ room
off_hold_release = { # 🦆 duck say ⮞ or "on_press_release" or "on_hold_release" or "up_press_release" or "up_hold_release" or "down_press_release" or "down_hold_release" or "off_press_release"
enable = true;
description = "Turn off all configured light devices";
extra_actions = []; # 🦆 duck say ⮞ writing your actions here won't override default actions
override_actions = [ # 🦆 duck say ⮞ writing them here will
{
type = "mqtt";
topic = "zigbee2mqtt/Fläkt/set";
message = ''{"state":"OFF"}'';
}
{
type = "scene";
scene = "dark";
}
];
};
};
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
dimmer_actions = {
livingroom = {
off_hold_release = {
enable = true;
description = "Description of automation";
extra_actions = [];
override_actions = [
{
type = "mqtt";
topic = "zigbee2mqtt/Fläkt/set";
message = ''{"state":"OFF"}'';
}
{
type = "scene";
scene = "dark";
}
];
};
};
};
};
};
};}
Global Action Automations
Supported Global Action Triggers: "leak_detected" - When water sensors detect leaks. "smoke_detected" - When smoke detectors trigger.
If you have smoke detectors or water sensors, this is a very important example:
⮞ View `config.house.zigbee.automations.global_actions` code example
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
global_actions = { # 🦆 duck say ⮞ not room specific
leak_detected = [ # 🦆 duck say ⮞ WATER?! WARNING! - then take bath yay
{
type = "shell";
command = "${config.pkgs.yo}/bin/yo-notify '🚨 WATER LEAK DETECTED!'";
}
{
type = "mqtt";
topic = "zigbee2mqtt/all_valves/set";
message = ''{"state":"OFF"}'';
}
"echo 'EMERGENCY: Water leak!' | wall"
];
smoke_detected = [
{ # 🦆 duck say ⮞ dont like fire =(
type = "shell";
command = "${pkgs.paplay}/bin/paplay ${config.this.user.me.dotfilesDir}/modules/themes/sounds/fire-alarm.wav";
}
{
type = "mqtt";
topic = "zigbee2mqtt/all_lights/set";
message = ''{"state":"ON", "brightness": 255, "color": {"hex": "FF0000"}}'';
}
"curl -X POST http://localhost:8080/emergency/fire"
];
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
global_actions = {
leak_detected = [
{
type = "shell";
command = "${config.pkgs.yo}/bin/yo-notify '🚨 WATER LEAK DETECTED!'";
}
{
type = "mqtt";
topic = "zigbee2mqtt/all_valves/set";
message = ''{"state":"OFF"}'';
}
"echo 'EMERGENCY: Water leak!' | wall"
];
smoke_detected = [
{
type = "shell";
command = "${pkgs.paplay}/bin/paplay ${config.this.user.me.dotfilesDir}/modules/themes/sounds/fire-alarm.wav";
}
{
type = "mqtt";
topic = "zigbee2mqtt/all_lights/set";
message = ''{"state":"ON", "brightness": 255, "color": {"hex": "FF0000"}}'';
}
"curl -X POST http://localhost:8080/emergency/fire"
];
};
};
};
};}
Room Action Automations
Supported Room Action Triggers: "motion_detected" - When motion sensors detect movement.
Default Action: Turn on all light devices in the motion sensors room. (if darkTime) "motion_not_detected" - When motion stops being detected.
Default Action: Turn off all light devices in the motion sensors room. (after time configured in darkTime) "door_opened" - When door/window sensors open. "door_closed" - When door/window sensors close.
Take a look at an example snippet of how a room action automation may look:
⮞ View `config.house.zigbee.automations.room_actions` code example
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
room_actions = {
hallway = { # 🦆 duck say ⮞ room
# 🦆 says ⮞ zigbee device must be configured as type 'sensor'
door_opened = [];
door_closed = [];
};
bedroom = {
# 🦆 says ⮞ default actions already configured - room lights will turn on upon motion (if darkTime)
motion_detected = [
{
type = "scene";
scene = "Chill Scene";
}
];
motion_not_detected = [
{
type = "mqtt"; # 🦆 duck say ⮞ or "shell" or "scene"
topic = "zigbee2mqtt/Sänggavel/set";
message = ''{"state":"OFF", "brightness": 80}'';
}
];
};
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
room_actions = {
hallway = {
door_opened = [];
door_closed = [];
};
bedroom = {
motion_detected = [
{
type = "scene";
scene = "Chill Scene";
}
];
motion_not_detected = [
{
type = "mqtt";
topic = "zigbee2mqtt/Sänggavel/set";
message = ''{"state":"OFF", "brightness": 80}'';
}
];
};
};
};
};
};}
MQTT Triggered Automations
Triggers the automation when a specified Mosquitto topic (and optionally message) is received and processed.
This enables the user to automate, well - basically anything. Supported MQTT triggered Conditions: "dark_time" - Checks: If current time is within configured dark time range.
⮞ View usage
{ type = "dark_time"; }
{ type = "dark_time"; }
Here is an example snippet of how the mqtt triggered automation may look:
⮞ View `config.house.zigbee.automations.mqtt_triggered` code example
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
mqtt_triggered = {
dashboard_command = {
enable = true;
description = "Handle custom commands from web dashboard";
topic = "house/command";
message = null; # 🦆 says ⮞ match any message on this topic
actions = [
{ # 🦆says⮞ these variables are passed to the shell script for usage
type = "shell";
command = ''
echo "Topic: $MQTT_TOPIC"
echo "Device: $MQTT_DEVICE"
echo "Room: $MQTT_ROOM"
echo "Payload: $MQTT_PAYLOAD"
echo "Action: $MQTT_ACTION"
echo "State: $MQTT_STATE"
'';
}
];
};
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
mqtt_triggered = {
dashboard_command = {
enable = true;
description = "Handle custom commands from web dashboard";
topic = "house/command";
message = null;
actions = [
{
type = "shell";
command = ''
echo "Topic: $MQTT_TOPIC"
echo "Device: $MQTT_DEVICE"
echo "Room: $MQTT_ROOM"
echo "Payload: $MQTT_PAYLOAD"
echo "Action: $MQTT_ACTION"
echo "State: $MQTT_STATE"
'';
}
];
};
};
};
};
};}
Time Based Action Automations
Triggers the automation on a specified time and days. Supported Time Based Conditions: "dark_time" - Checks: If current time is within configured dark time range.
⮞ View usage
{ type = "dark_time"; }
{ type = "dark_time"; }
Here is an example snippet of how the time based automation may look:
⮞ View `config.house.zigbee.automations.time_based` code example
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
time_based = {
smart_wakeup = { # 🦆 duck say ⮞ pick a name
enable = true;
description = "Gradual wake-up with news and coffee";
schedule = { # 🦆 duck say ⮞ when to run
start = "06:30";
end = "07:00";
days = ["mon" "tue" "wed" "thu" "fri"]; # 🦆 duck say ⮞ and what days
};
conditions = [ # 🦆 duck say ⮞ only run when someone is home qwack
{ type = "someone_home"; value = true; }
];
actions = [
{
type = "scene";
scene = "sunrise_simulation";
}
{
type = "shell";
command = "${pkgs.mpg123}/bin/mpg123 ${config.this.user.me.dotfilesDir}/modules/themes/sounds/alarm.mp3";
}
{
type = "mqtt";
topic = "zigbee2mqtt/CoffeeMaker/set";
message = ''{"state":"ON", "time": 300}'';
}
{
type = "shell";
command = "${config.pkgs.yo}/bin/yo-say 'Good morning! Time to wake up.'";
}
];
};
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
time_based = {
smart_wakeup = {
enable = true;
description = "Gradual wake-up with news and coffee";
schedule = {
start = "06:30";
end = "07:00";
days = ["mon" "tue" "wed" "thu" "fri"];
};
conditions = [
{ type = "someone_home"; value = true; }
];
actions = [
{
type = "scene";
scene = "sunrise_simulation";
}
{
type = "shell";
command = "${pkgs.mpg123}/bin/mpg123 ${config.this.user.me.dotfilesDIr}/modules/themes/sounds/alarm.mp3";
}
{
type = "mqtt";
topic = "zigbee2mqtt/CoffeeMaker/set";
message = ''{"state":"ON", "time": 300}'';
}
{
type = "shell";
command = "${config.pkgs.yo}/bin/yo-say 'Good morning! Time to wake up.'";
}
];
};
};
};
};
};}
Presence Based Action Automations
Supported Presence Based Conditions: "someone_home" - Checks: If someone is home.
⮞ View usage
{
type = "someone_home";
value = true;
}
{
type = "someone_home";
value = true;
}
"room_occupied" - Checks: If a specific room is occupied.
⮞ View usage
{
type = "room_occupied";
room = "livingroom";
value = true;
}
{
type = "room_occupied";
room = "livingroom";
value = true;
}
Here is an example snippet of how the presence based automations may look:
⮞ View `config.house.zigbee.automations.presence_based` code example
{ # 🦆 duck say ⮞ my house - qwack
config,
lib,
pkgs,
...
} : let
in { # 🦆 duck say ⮞ autoqwack
house = {
zigbee = {
automations = {
presence_based = {
arrival_party = { # 🦆 duck say ⮞ automation name
enable = true;
description = "Fun lighting when arriving home";
motion_sensors = ["Front Door Motion"]; # 🦆 duck say ⮞ wat motion sensors 2 be affected
no_motion_duration = 30; # 🦆 duck say ⮞ seconds
conditions = [
{ type = "dark_time"; }
];
actions = [ # 🦆 duck say ⮞ u knowz dis by now
{
type = "scene";
scene = "welcome_home";
}
{
type = "mqtt";
topic = "zigbee2mqtt/DiscoBall/set";
message = ''{"state":"ON", "speed": 200}'';
}
];
};
};
};
};
};}
{
config,
lib,
pkgs,
...
} : let
in {
house = {
zigbee = {
automations = {
presence_based = {
arrival_party = {
enable = true;
description = "Fun lighting when arriving home";
motion_sensors = ["Front Door Motion"];
no_motion_duration = 30;
conditions = [
{ type = "dark_time"; }
];
actions = [
{
type = "scene";
scene = "welcome_home";
}
{
type = "mqtt";
topic = "zigbee2mqtt/DiscoBall/set";
message = ''{"state":"ON", "speed": 200}'';
}
];
};
};
};
};
};}
Important Notes:
Room names must match your house.rooms configuration.
Device names must match exactly what's in house.zigbee.devices
Global actions fire regardless of room context.
Room actions only fire for devices in that specific room.
All actions run sequentially when the trigger condition is met.
I hope you do see the full potential of this powerful automation system.
I realize it's a lot to take in at once, but hopefully I made it pretty clear of how it all works.
The examples are very basic, and that is how I recommend you start out if you are aiming to test this out.
Extending the configurations into complex automations is so simple it needs no instructions.
Comments on this blog post