Skip to content

Triggers

The trigger decides when an entry is active. Conditions and actions only matter while it is active. This page covers starting by time; starting by event or by sensor is a trigger plus entry conditions (see Concepts and Conditions).

The Trigger Type list

Summary

Trigger Type (UI) API Fields Active
Recurring windows when_spec (no trigger_kind) Days, one or more time windows inside any window, on the ticked days
One-off date window when_spec.date Date, one or more time windows inside any window, on that date only
Daily at time trigger_kind: daily Fire at, Duration (min) fire time → + duration, every day
Weekly at time weekly Days, Fire at, Duration (min) fire time → + duration, on the ticked days
Every N minutes interval Every (min), Anchor, Duration (min) each fire → + duration
Monthly / calendar monthly Day of month, Fire at, Duration (min), Months fire time → + duration
Custom cron cron Cron expression, Duration (min) each cron match → + duration
Always evaluate (sensor-driven) always — always
(API only) oneoff fire_at (ISO date-time), duration_s fire time → + duration, once

Window triggers are legacy entries unless they also have conditions; the others are v2. See Concepts.

Fire-based triggers: the active window

For Daily, Weekly, Every N minutes, Monthly, Cron and the API one-off, the bridge finds the most recent fire time at or before now. The entry is active from that fire time until fire time + Duration (min).

Duration (min) empty or 0 means one minute

With no duration the active window is 60 seconds. That is enough for a one-shot action (a mode, a reserve, a notification). A force command sent in that minute is released about a minute later at the window end. Set a duration for force commands: an exit condition can end a run earlier, never later.

Duration (min) is not the same as Duration (HH:MM:SS)

Duration (min) sits with the trigger and sets how long the entry stays active. Duration (HH:MM:SS) sits under the entry conditions and is the hold-for time.

All triggers work to the minute: seconds are dropped before fire times are compared, so a fire time equal to the current minute counts as now.

Recurring windows

Recurring windows fields

  1. Tick the Days. None ticked means every day.
  2. Type a start → end time. + add window adds another; ✕ removes one (one must stay).
Field Values Notes
Days Mon … Sun, any combination None ticked = every day.
Time windows start → end, HH:MM Any window matching makes the entry active.
  • The entry is active from start up to, but not including, end.

  • None ticked = every day. A day not ticked is skipped.

  • Several windows on one entry: the entry is active inside any of them.

  • End earlier than start wraps past midnight. 22:00 → 06:00 runs overnight; the form says wraps past midnight.

  • The day check uses today's date, not the day the window opened. With only Mon ticked, 22:00 → 06:00 is active Monday 00:00–06:00 and Monday 22:00–24:00, not Monday night into Tuesday. Tick both days if you want both halves.

  • Start equal to end matches nothing.

  • 24:00 is midnight. An end of 24:00 is read as 00:00, so 18:00 → 24:00 runs to midnight. The API accepts H:MM or HH:MM; hours above 23 wrap.

One-off date window

One-off date window fields

Field Values Notes
Date a calendar date Defaults to the bridge's today.
Time windows start → end Same rules as recurring windows.
  • The entry is active only on that date. The Days are ignored.

  • It never fires again. The list shows Once (passed) after the date.

  • An overnight window on a date covers only that date: 22:00 → 02:00 on 20 October runs 00:00–02:00 and 22:00–24:00 on the 20th. Use two entries to cross midnight.

Daily at time

Daily fields

Field Values
Fire at HH:MM
Duration (min) 0 or more (0 = one minute)

A duration longer than 24 hours makes the windows overlap, so the entry never becomes inactive (see Always for what that means after a run ends).

Weekly at time

Weekly fields

Field Values Notes
Days Mon … Sun Tick at least one day.
Fire at HH:MM
Duration (min) 0 or more

A weekly trigger with no days never fires. The bridge accepts it when you save; Next fire shows —.

Every N minutes

Interval fields

Field Values Notes
Every (min) 1 or more Stored as seconds (every_seconds). The API takes any positive number of seconds.
Anchor HH:MM, optional Fires are counted from this time. Empty = midnight.
Duration (min) 0 or more
  • Fires land on anchor + k × N, counted from today's anchor (or yesterday's, before the anchor time). With N = 30 and no anchor: 00:00, 00:30, 01:00 …

  • The count restarts at the anchor every day. If N does not divide 24 hours, the last gap of the day is shorter: every 7 hours from midnight fires 00:00, 07:00, 14:00, 21:00, then 00:00 again.

  • 24 hours or more behaves like Daily at the anchor time.

  • An interval of 0 or less, or one that isn't a number, never fires. The form never sends one.

Monthly / calendar

Monthly fields

Field Values Notes
Day of month 1–31 Clamped to the month's length: 31 fires on 30 April and 28/29 February.
Fire at HH:MM Empty (API) = 00:00.
Duration (min) 0 or more
Months Jan … Dec None ticked = every month.

The quick presets use this trigger: Every month (1st day), Quarterly (Jan, Apr, Jul, Oct), Six monthly (Jan, Jul) and Annually (Jan 1st).

Custom cron

Cron fields

Field Values
Cron expression five fields: minute, hour, day of month, month, day of week
Duration (min) 0 or more
Expression Fires
*/15 * * * * every 15 minutes
0 17 * * 1-5 17:00 Monday–Friday
*/30 6-20 * * * every half hour from 06:00 to 20:30
0 0 1 * * midnight on the 1st of each month
  • The bridge checks the expression when you save and refuses an invalid one.

  • Day of week counts from Sunday = 0 (Monday = 1) in cron, unlike the Weekly trigger and time.dow, where Monday = 0.

  • A cron match at the current minute counts as now.

  • Cron and monthly entries are not drawn on the visual timeline.

Always evaluate

Always evaluate

The entry is active all the time; only its entry conditions decide whether it dispatches.

Always runs once, then waits for a restart

The form says an Always entry "releases when [its conditions] stop". The code does not do that:

  • Once a force command runs, the entry conditions are not checked again. Only an exit condition, a time limit, a target SoC, Stop or a release elsewhere ends it.
  • When a run ends, the entry is marked done for this window. An Always window never closes, so the entry does not fire again until the bridge restarts.
  • An Always HA-only entry also fires its HA actions only once per bridge run.
  • The done mark is held per gateway, not per entry. If another entry on the same target dispatches, the mark is cleared and the Always entry can fire again. Disabling and re-enabling the entry does not clear it when it is the only entry on its target.

For "whenever the price is low" rules use a repeating trigger with a gap, for example Custom cron */30 * * * * with a 29-minute duration. The examples do this.

Quick presets

Quick presets

A preset fills the trigger fields; you can edit them afterwards.

Preset Sets
Every 5 / 10 / 15 / 30 minutes, Every minute, Every hour Every N minutes, N = 5, 10, 15, 30, 1, 60
Every day (midnight), Every day (morning 8am) Daily at 00:00 / 08:00
Every week (Sun midnight) Weekly, Sunday, 00:00
Every month (1st day), Quarterly, Six monthly, Annually Monthly, day 1, months as named
Custom cron expression… Custom cron

Next fire

The Next fire column is worked out on the bridge, on the bridge's clock:

The When and Next fire columns

Trigger Next fire
Recurring windows the next window start at or after now, looking up to 8 days ahead. While a window is open, that is the next one, not the current one.
One-off date window the next window start on that date; — once it has passed
Fire-based the next fire time at or after now
Always, or a trigger that can never fire —

Editing a trigger in the form

  • Switching a fire-based entry to a window type keeps the old Duration (min) in the database. A window ignores it for activity, but Run now still uses it as the time limit (see Run now).

  • An API one-off (trigger_kind: oneoff) has no form type. Opening it in the editor and saving it drops its fire_at, and the entry never fires again.

After an outage or a restart (catch-up)

The bridge treats a gateway as in an outage when no good poll has arrived for more than 60 seconds. When the gateway is back, the bridge runs catch-up for every enabled entry that targets it. It also runs at start-up when the bridge was down for more than 60 seconds, using the last good poll it saved (every 60 s) before stopping.

For each entry:

Situation What happens
Its window is open now Nothing special: the next tick handles it as usual (gate permitting).
A window start or fire time fell inside the outage and has ended Handled by If missed during an outage, below. Only the latest missed fire counts (for windows, the first window start after the outage began).
No fire during the outage Nothing.
Always entries Never missed: they have no fire time.

If missed during an outage

Option (UI) API missed_policy Behaviour
resume if window still open, else log missed late_fire_remaining (default) Logs missed.
skip (log missed only) skip Logs missed. Behaves exactly like the default.
late-fire even if window passed late_fire_always Checks the entry conditions now. If they pass, sends the action now and logs late_fired; otherwise logs missed with the failing values.

A late fire is different from a normal run:

  • It is not owned by the scheduler: no exit conditions, no verification, no release at a window end. It ends at its time limit (the entry's duration) or when something releases it. An entry with no duration late-fires with no time limit.

  • It ignores If already controlled: it is sent even over a manual command.

  • It runs no HA actions. An HA-only (none) entry with this policy sends nothing and writes no Activity Log row; it is only listed as missed on the outage record.

  • Its Activity Log rows name the target as gateway:<id>:<gateway> rather than the gateway's name.

The form shows the missed-policy selector only for fire-based triggers. Window entries are caught up with whatever policy is stored on them; the form saves its current value (normally the default).

The clock that all of this runs on is described in Restarts and the clock.