Skip to main content

Overview

Every Action needs a trigger—the event that starts its execution. Choosing the right trigger type determines how your automation responds to real-world conditions.
Think of triggers like different ways to start your car. A time-based trigger is like an auto-start that warms up your car every morning at 7 AM. A topic-based trigger is like pushing the start button when you get in. A callable action is like asking someone else to start it for you.

When to Use Each Type

Trigger TypeUse WhenExample
Time-Based (ON EVERY, ON TIMESTAMP)You need a clock-driven schedule (interval or wall-clock)Heartbeats, polling, shift windows, one-shot cutovers
Topic-Based (ON TOPIC)You need to react when data arrivesSensor processing, command handling
Initialization (ON START)You need to run logic once when the broker startsBootstrap UNS structure, set default config values
Callable (no trigger)You need reusable logic invoked by other actionsUtility functions, shared calculations

In This Page

  • Time-Based Triggers — Intervals, weekday/weekend rules, and ON TIMESTAMP (daily or one-shot)
  • Topic-Based Triggers — React to MQTT messages with ON TOPIC
  • Initialization Triggers — Run once at broker startup with ON START
  • Callable Actions — Invoke manually or from other actions

Time-Based Triggers

LoT supports several time-based trigger forms. All of them use the ON keyword and run the action’s DO block automatically—no MQTT message is required to fire them. Together they cover recurring intervals, calendar rules (a specific weekday, Monday–Friday, or Saturday–Sunday), daily wall-clock times, and single one-shot executions.

Quick reference

SyntaxPatternRecurs?
ON EVERY N UNITEvery N seconds, minutes, hours, and so onYes — indefinitely
ON EVERY DAY AT "HH:mm"Named weekday at a fixed local timeYes — every week
ON EVERY WEEKDAY AT "HH:mm"Monday–Friday at a fixed local timeYes — every weekday
ON EVERY WEEKEND AT "HH:mm"Saturday–Sunday at a fixed local timeYes — every weekend
ON TIMESTAMP "HH:mm:ss"Every day at a fixed local timeYes — every day
ON TIMESTAMP "dd-MM-yyyy HH:mm:ss"Exact date and timeNo — one-shot
Time zone: For HH:mm and HH:mm:ss in ON EVERY … AT and in daily ON TIMESTAMP, values are interpreted in the local time of the machine running the broker, then converted to UTC internally. The action is scheduled for the correct wall-clock time across daylight saving changes. The one-shot form dd-MM-yyyy HH:mm:ss is interpreted as UTC, as described below.
Structured payloads: PUBLISH TOPIC does not support inline JSON object literals. For multi-field records, define a COLLAPSED model and use PUBLISH MODEL … TO … WITH (see Publishing Models). The timed-action examples below use that pattern.

1. ON EVERY N UNIT — fixed interval

Fires repeatedly every N units of time. Common for monitoring, polling, and heartbeats.
DEFINE ACTION <Name>
ON EVERY <N> <UNIT> DO
    -- body

Supported units

Keyword(s)Example
MILLISECOND / MSON EVERY 500 MS
SECOND / SECONDSON EVERY 30 SECONDS
MINUTE / MINUTESON EVERY 5 MINUTES
HOUR / HOURSON EVERY 1 HOUR
DAY / DAYSON EVERY 1 DAY
WEEK / WEEKSON EVERY 2 WEEKS
MONTH / MONTHSON EVERY 1 MONTH
YEAR / YEARSON EVERY 1 YEAR
Singular and plural unit names are interchangeable (for example, 1 SECOND and 1 SECONDS). ON EVERY 1 DAY fires every 24 hours from the last run; for the same clock time every calendar day, use daily ON TIMESTAMP instead.
DEFINE ACTION SystemHeartbeat
ON EVERY 5 SECONDS DO
    PUBLISH TOPIC "system/heartbeat" WITH "alive"
    PUBLISH TOPIC "system/heartbeat/timestamp" WITH TIMESTAMP "UTC"
DEFINE ACTION PollMachineTemperature
ON EVERY 30 SECONDS DO
    SET "temp" WITH GET TOPIC "machine/sensor/temperature"
    IF {temp} > 85 THEN
        PUBLISH TOPIC "alerts/temperature/high" WITH {temp}
    PUBLISH TOPIC "machine/temperature/last_check" WITH TIMESTAMP "UTC"
DEFINE ACTION FastSensorSample
ON EVERY 500 MS DO
    PUBLISH TOPIC "sensors/vibration/sample" WITH GET TOPIC "sensors/vibration/raw"

2. ON EVERY DAY AT — weekly, specific day

Fires once per week on the named weekday at the given local time. Use "HH:mm" or "HH:mm:ss"; seconds are optional.
KeywordFires on
MONDAYSUNDAYThat weekday each week
DEFINE ACTION <Name>
ON EVERY MONDAY AT "08:00:00" DO
    -- body
DEFINE MODEL ProductionWeeklyReport COLLAPSED
    ADD STRING "week"
    ADD INT "total_parts"
    ADD INT "total_rejects"

DEFINE ACTION WeeklyProductionReport
ON EVERY MONDAY AT "08:00:00" DO
    SET "week_total" WITH GET TOPIC "factory/line1/parts_produced"
    SET "week_rejects" WITH GET TOPIC "factory/line1/rejects"
    PUBLISH MODEL ProductionWeeklyReport TO "reports/weekly/production" WITH
        week = TIMESTAMP "UTC"
        total_parts = {week_total}
        total_rejects = {week_rejects}
    PUBLISH TOPIC "factory/line1/parts_produced" WITH 0
    PUBLISH TOPIC "factory/line1/rejects" WITH 0

3. ON EVERY WEEKDAY AT — Monday–Friday

Fires Monday through Friday at the same local time—one action instead of five separate daily schedules.
DEFINE MODEL ShiftMorningBriefing COLLAPSED
    ADD STRING "line_status"
    ADD STRING "pending_orders"
    ADD STRING "shift_start"

DEFINE ACTION ShiftStartBriefing
ON EVERY WEEKDAY AT "07:30" DO
    SET "line_status" WITH GET TOPIC "factory/line1/status"
    SET "pending_orders" WITH GET TOPIC "erp/orders/pending"
    PUBLISH MODEL ShiftMorningBriefing TO "shift/briefing/morning" WITH
        line_status = {line_status}
        pending_orders = {pending_orders}
        shift_start = TIMESTAMP "UTC"

4. ON EVERY WEEKEND AT — Saturday and Sunday

Fires on both weekend days at the specified local time—useful for maintenance windows or weekend-only reporting.
DEFINE ACTION WeekendMaintenanceWindow
ON EVERY WEEKEND AT "06:00:00" DO
    PUBLISH TOPIC "maintenance/window/open" WITH "true"
    PUBLISH TOPIC "maintenance/window/start" WITH TIMESTAMP "UTC"
    PUBLISH TOPIC "notifications/maintenance" WITH "Weekend maintenance window is now open"

5. ON TIMESTAMP — daily fixed time

Fires every day at the given local wall-clock time. Unlike ON EVERY 1 DAY, this tracks clock time, not elapsed time since the broker or last run started.
DEFINE ACTION <Name>
ON TIMESTAMP "08:00:00" DO
    -- body
"HH:mm" without seconds is accepted.
DEFINE ACTION DailyCounterReset
ON TIMESTAMP "00:00:00" DO
    PUBLISH TOPIC "factory/line1/parts_produced" WITH 0
    PUBLISH TOPIC "factory/line1/rejects" WITH 0
    PUBLISH TOPIC "factory/line1/day_start" WITH TIMESTAMP "UTC"

6. ON TIMESTAMP — one-shot, exact date and time

Fires once at the exact instant given, then never again (the scheduler moves the next run far into the future). Format is strictly dd-MM-yyyy HH:mm:ss (day–month–year). The timestamp is treated as UTC.
DEFINE ACTION SystemCutoverNotice
ON TIMESTAMP "01-04-2026 06:00:00" DO
    PUBLISH TOPIC "system/cutover/notice" WITH "New firmware version going live in 1 hour"
    PUBLISH TOPIC "notifications/all" WITH "Scheduled maintenance begins at 07:00 UTC"

Combination patterns

Real systems often split schedules across several actions—one trigger per concern.
DEFINE MODEL DailyTemperatureReport COLLAPSED
    ADD DOUBLE "max"
    ADD DOUBLE "min"
    ADD STRING "date"

DEFINE ACTION SensorPoll
ON EVERY 10 SECONDS DO
    SET "value" WITH GET TOPIC "sensors/temperature/raw"
    PUBLISH TOPIC "sensors/temperature/current" WITH {value}

DEFINE ACTION DailySensorSummary
ON TIMESTAMP "00:00:00" DO
    SET "max" WITH GET TOPIC "sensors/temperature/max"
    SET "min" WITH GET TOPIC "sensors/temperature/min"
    PUBLISH MODEL DailyTemperatureReport TO "reports/daily/temperature" WITH
        max = {max}
        min = {min}
        date = TIMESTAMP "UTC"
    PUBLISH TOPIC "sensors/temperature/max" WITH 0
    PUBLISH TOPIC "sensors/temperature/min" WITH 0
DEFINE ACTION WeekdayProductionStart
ON EVERY WEEKDAY AT "06:00" DO
    PUBLISH TOPIC "factory/line1/mode" WITH "production"
    PUBLISH TOPIC "factory/line1/shift_start" WITH TIMESTAMP "UTC"

DEFINE ACTION WeekendMaintenance
ON EVERY WEEKEND AT "07:00" DO
    PUBLISH TOPIC "factory/line1/mode" WITH "maintenance"
    PUBLISH TOPIC "notifications/maintenance/start" WITH TIMESTAMP "UTC"
DEFINE MODEL DashboardThroughput COLLAPSED
    ADD INT "parts"
    ADD DOUBLE "rate_per_min"
    ADD INT "updated"

DEFINE ACTION WeeklyKpiReset
ON EVERY MONDAY AT "00:00:00" DO
    PUBLISH TOPIC "kpi/weekly/parts_produced" WITH 0
    PUBLISH TOPIC "kpi/weekly/reset_time" WITH TIMESTAMP "UTC"

DEFINE ACTION DailyKpiSnapshot
ON TIMESTAMP "23:59:00" DO
    SET "daily_parts" WITH GET TOPIC "factory/line1/parts_produced"
    PUBLISH TOPIC "kpi/daily/snapshot" WITH {daily_parts}
    PUBLISH TOPIC "kpi/daily/snapshot_time" WITH TIMESTAMP "UTC"

DEFINE ACTION LiveThroughput
ON EVERY 1 MINUTE DO
    SET "parts" WITH GET TOPIC "factory/line1/parts_produced"
    SET "rate" WITH GET TOPIC "factory/line1/production_rate"
    PUBLISH MODEL DashboardThroughput TO "dashboard/live/throughput" WITH
        parts = {parts}
        rate_per_min = {rate}
        updated = TIMESTAMP "UNIX"
DEFINE ACTION CutoverActivation
ON TIMESTAMP "01-07-2026 06:00:00" DO
    PUBLISH TOPIC "system/version" WITH "2.0"
    PUBLISH TOPIC "system/cutover/complete" WITH TIMESTAMP "UTC"

DEFINE ACTION V2Heartbeat
ON EVERY 30 SECONDS DO
    SET "ver" WITH GET TOPIC "system/version"
    IF {ver} EQUALS "2.0" THEN
        PUBLISH TOPIC "system/v2/heartbeat" WITH "running"

Error handling

If a time string does not match an expected format, the broker logs an error similar to: Invalid DATE_TIME format: <value>. Expected formats:
  • dd-MM-yyyy HH:mm:ss (one-time)
  • HH:mm:ss / HH:mm (daily)
  • Weekly forms using a day name with AT and a time string
Errors are also published (retained) to: $SYS/Coreflux/Actions/<ActionName>/Error Subscribe to $SYS/Coreflux/Actions/+/Error to observe failures from any action.

At a glance — valid time triggers

ON EVERY 500 MS DO
ON EVERY 10 SECONDS DO
ON EVERY 5 MINUTES DO
ON EVERY 1 HOUR DO
ON EVERY 1 DAY DO
ON EVERY 1 WEEK DO
ON EVERY 1 MONTH DO
ON EVERY MONDAY AT "08:00:00" DO
ON EVERY WEEKDAY AT "07:30" DO
ON EVERY WEEKEND AT "06:00" DO
ON TIMESTAMP "07:00" DO
ON TIMESTAMP "00:00:00" DO
ON TIMESTAMP "25-12-2026 09:00:00" DO

More examples

DEFINE ACTION SystemHeartbeat
ON EVERY 5 SECONDS DO
    PUBLISH TOPIC "system/status" WITH "online"
    PUBLISH TOPIC "system/timestamp" WITH TIMESTAMP "UTC"
DEFINE ACTION IncrementCounter
ON EVERY 10 SECONDS DO
    IF GET TOPIC "counter/value" == EMPTY THEN
        PUBLISH TOPIC "counter/value" WITH 0
    ELSE
        PUBLISH TOPIC "counter/value" WITH (GET TOPIC "counter/value" + 1)

Topic-Based Triggers

Use ON TOPIC to execute actions when MQTT messages arrive:
DEFINE ACTION ProcessMessage
ON TOPIC "input/data" DO
    PUBLISH TOPIC "output/data" WITH PAYLOAD

Wildcard Patterns

LoT supports MQTT wildcards for flexible topic matching:
The + wildcard matches exactly one topic level:
DEFINE ACTION SensorRouter
ON TOPIC "sensors/+/temperature" DO
    // POSITION 1="sensors", POSITION 2=wildcard (sensor_id), POSITION 3="temperature"
    SET "sensor_id" WITH TOPIC POSITION 2
    PUBLISH TOPIC "processed/" + {sensor_id} + "/temp" WITH PAYLOAD
Matches: sensors/room1/temperature, sensors/room2/temperature
Does NOT match: sensors/building1/floor2/temperature (too many levels)

Initialization Triggers

Use ON START to execute logic exactly once when the broker starts or when the action is first deployed. This is the right place to bootstrap a Unified Namespace (UNS) structure, publish retained default configurations, and log startup events.
DEFINE ACTION InitUNSRoot
ON START DO
    KEEP TOPIC "config/uns_root" WITH "factory/lisbon"
    KEEP TOPIC "factory/info/name" WITH "Lisbon Plant"
    KEEP TOPIC "factory/info/timezone" WITH "Europe/Lisbon"
    PUBLISH TOPIC "system/log" WITH "UNS root initialised"
Key characteristics:
  • Runs exactly once per broker start — not on a schedule, not on a message
  • KEEP TOPIC publishes with the retain flag so the value is delivered to any future subscriber immediately on connection
  • Use it to set default configuration values and retained state that must survive restarts
  • There is no ON STOP equivalent — ON START is the correct place for setup logic

Callable Actions

Actions without an event trigger are callable—they execute only when explicitly invoked by other actions or via system commands.

Basic Callable Action

DEFINE ACTION CacheUpdater
DO
    KEEP TOPIC "cache/latest" WITH (GET TOPIC "data/current")
    PUBLISH TOPIC "cache/updated" WITH TIMESTAMP "UTC"

Callable Action with Parameters

Callable actions can accept input parameters and return values:
DEFINE ACTION CalculateAverage
INPUT value1 AS DOUBLE
INPUT value2 AS DOUBLE
DO
    SET "sum" WITH ({value1} + {value2})
    SET "avg" WITH ({sum} / 2)
RETURN
    OUTPUT avg

Invoking Callable Actions

Use CALL ACTION to invoke from within another action. This is the primary way to reuse logic across your automation:
DEFINE ACTION ProcessSensorPair
ON TOPIC "sensors/pair/data" DO
    SET "temp1" WITH (GET JSON "sensor1" IN PAYLOAD AS DOUBLE)
    SET "temp2" WITH (GET JSON "sensor2" IN PAYLOAD AS DOUBLE)
    
    CALL ACTION CalculateAverage
        WITH value1 = {temp1}, value2 = {temp2}
        RETURN result
    
    PUBLISH TOPIC "sensors/average" WITH {result}

Comparing Trigger Types

AspectTime-BasedTopic-BasedON STARTCallable
TriggerClock interval or scheduleMQTT messageBroker startupManual command
FrequencyInterval, daily, weekly, or onceEvent-drivenOnceOn-demand
Payload AccessNoYes (PAYLOAD)NoVia parameters
Best ForMonitoring, reportingData processingInitializationReusable utilities

Next Steps

Operations

Learn about SET, GET, PUBLISH, and conditional logic.

Python Integration

Extend Actions with Python for complex calculations.