LOT Actions
1. Introduction
The Coreflux LOT scripting language is used to define Actions—small logic blocks that react to events (time-based or topic-based) and publish data to topics. This document details each element of the syntax so you can understand how LOT interprets your code.
For practical examples of LOT Actions, check out the Actions examples in the LOT Samples Repository.
1.1 Overall Structure
Each Action starts with the keyword:
followed by one of the event triggers (e.g., ON EVERY ..., ON TOPIC ..., etc.) and a logic block describing what to do when that event occurs. Within the logic block, you can use IF statements, or simply do one or more PUBLISH instructions.
Example structure:
1.2 Indentation
LOT uses indentation to visually separate blocks of code and highlight logic flow. While indentation levels can be set by tabs or spaces, be consistent.
- Top-level lines (like DEFINE ACTION MyActionandON EVERY 5 SECONDS DO) begin at the leftmost column.
- Nested lines (the statements inside the DOblock, or inside anIF THENorELSEblock) are indented.
This helps LOT (and readers) understand which statements belong to which blocks.
2. Event Triggers
An Action is activated by specifying the condition or event that should trigger its execution. Some common triggers are:
- ON EVERY <time>– runs on a repeating interval.
- Example: ON EVERY 5 SECONDS DOexecutes the block every 5 seconds.
- 
Other intervals can be MINUTES,HOURS, etc.
- 
ON TOPIC <topic>– runs whenever the specified topic is published to.
- Example: ON TOPIC "myTopic" DOexecutes whenever a message arrives on"myTopic".
3. Expressions in LOT
LOT expressions can retrieve data from a topic, compare values, or perform mathematical operations.
3.1 GET TOPIC "<topic>"
Retrieves the most recent payload of a specific MQTT topic.
Example:
3.2 Mathematical Operations
The following operators are supported on numeric values:
- +(addition)
- -(subtraction)
- *(multiplication)
- /(division)
- %(modulo, returns the remainder of a division)
Example:
3.3 Comparisons
You can compare values using ==, !=, <, >, <=, >=, etc.  
Example:
(Both == and EQUALS can be used;)
4. The IF THEN ELSE Logic
LOT supports conditional logic through an IF <expression> THEN and optional ELSE:
- Condition: A boolean expression (e.g., GET TOPIC "switchState" == "off").
- THEN block: One or more PUBLISH statements (or other logic).
- ELSE block (optional): Executed when the condition is not met.
Example:
IF GET TOPIC "my/light" == "off" THEN
    PUBLISH TOPIC "my/light" WITH "on"
ELSE
    PUBLISH TOPIC "my/light" WITH "off"
5. Special Keywords
5.1 PAYLOAD
PAYLOAD refers to the value that triggered the Action in an ON TOPIC event. Whenever an action is triggered by a topic publication, PAYLOAD holds that newly published value.
For instance, in an action triggered by ON TOPIC "input2/topic":
DEFINE ACTION MyAction
ON TOPIC "input2/topic" DO
    PUBLISH TOPIC "some/otherTopic" WITH (PAYLOAD + 1)
- Here, PAYLOADis the last message content published toinput2/topic.
- (PAYLOAD + 1)increments that value, then publishes the result.
5.2 TIMESTAMP
TIMESTAMP is used to insert the current date/time (in UTC or local format, depending on your syntax) into the published data.
- This sends a message to "my/topic"that contains a JSON object or string with the current UTC time (exact format may depend on your Coreflux version).
5.3 CALL PYTHON (Version 1.7.2+)
CALL PYTHON allows you to execute Python functions directly from LOT actions. This feature integrates Python code seamlessly into your IoT automation workflows.
Syntax
Parameters
- ScriptName: The name of the Python script (defined by # Script Name:comment)
- function_name: The specific function to call within that script
- WITH: Parameters to pass to the Python function
- RETURN AS: Variable name to store the function's return value
Examples
Basic Python Function Call
DEFINE ACTION PythonExample
ON TOPIC "python/test" DO
    CALL PYTHON "Calculator.add"
        WITH (5, 3)
        RETURN AS {result}
    PUBLISH TOPIC "math/result" WITH {result}
Using Topic Data with Python
DEFINE ACTION TextProcessor
ON TOPIC "text/input" DO
    SET message GET TOPIC "text/input" AS STRING
    CALL PYTHON "TextProcessor.reverse_text"
        WITH ({message})
        RETURN AS {reversed_text}
    PUBLISH TOPIC "text/reversed" WITH {reversed_text}
Multiple Python Calls in One Action
DEFINE ACTION DataProcessor
ON TOPIC "data/input" DO
    SET raw_data GET TOPIC "data/input" AS JSON
    CALL PYTHON "DataProcessor.validate"
        WITH ({raw_data})
        RETURN AS {validation_result}
    IF {validation_result} EQUALS "valid" THEN
        CALL PYTHON "DataProcessor.process"
            WITH ({raw_data})
            RETURN AS {processed_data}
        PUBLISH TOPIC "data/processed" WITH {processed_data}
    ELSE
        PUBLISH TOPIC "data/error" WITH {validation_result}
Python Function with No Parameters
DEFINE ACTION TimeAction
ON TOPIC "time/now" DO
    CALL PYTHON "TimeUtils.get_current_time"
        WITH ()
        RETURN AS {current_time}
    PUBLISH TOPIC "time/response" WITH {current_time}
Python Script Requirements
For Python functions to work with LOT actions, they must:
- Start with Script Name: Every Python script must begin with # Script Name: YourScriptName
- Be Added to Broker: Use the -addPythonMQTT command to register the script
- Handle Errors Gracefully: Use try-catch blocks to prevent broker crashes
- Return Compatible Types: Return values should be JSON-serializable
Example Python script:
# Script Name: Calculator
def add(a, b):
    return a + b
def multiply(a, b):
    return a * b
def divide(a, b):
    if b == 0:
        return {"error": "Cannot divide by zero"}
    return a / b
def safe_operation(operation, a, b):
    try:
        if operation == "add":
            return add(a, b)
        elif operation == "multiply":
            return multiply(a, b)
        elif operation == "divide":
            return divide(a, b)
        else:
            return {"error": "Unknown operation"}
    except Exception as e:
        return {"error": str(e)}
Error Handling
When Python functions encounter errors, the LOT action will receive the error information:
DEFINE ACTION SafePythonCall
ON TOPIC "safe/test" DO
    CALL PYTHON "Calculator.divide"
        WITH (10, 0)
        RETURN AS {result}
    IF {result} CONTAINS "error" THEN
        PUBLISH TOPIC "error/log" WITH {result}
    ELSE
        PUBLISH TOPIC "math/result" WITH {result}
Data Type Conversion
The system automatically handles data type conversions between LOT and Python:
- Numbers: LOT numbers become Python int/float
- Strings: LOT strings become Python strings
- Booleans: LOT booleans become Python booleans
- JSON: LOT JSON objects become Python dictionaries
- Arrays: LOT arrays become Python lists
Performance Considerations
- Python functions execute within the broker's Python.NET runtime
- Execution time is limited to prevent blocking the broker
- Memory usage is managed automatically
- Functions should be designed for quick execution in IoT contexts
6. Example Actions
Below are four sample Actions demonstrating the syntax.
6.1 StrokeGenerator
DEFINE ACTION StrokeGenerator
ON EVERY 5 SECONDS DO
    IF GET TOPIC "Coreflux/Porto/MeetingRoom/Light1/command/switch:0" EQUALS "off" THEN
        PUBLISH TOPIC "Coreflux/Porto/MeetingRoom/Light1/command/switch:0" WITH "on"
        PUBLISH TOPIC "Coreflux/Porto/MeetingRoom/Light1/command/switch:0/counter" WITH (GET TOPIC "Coreflux/Porto/MeetingRoom/Light1/command/switch:0/counter" + 1)
    ELSE
        PUBLISH TOPIC "Coreflux/Porto/MeetingRoom/Light1/command/switch:0" WITH "off"
- Trigger: Every 5 seconds.
- Logic:
- Retrieves the current state of "Coreflux/Porto/MeetingRoom/Light1/command/switch:0".
- If that state is "off", turn it"on"and increment its counter.
- Otherwise, turn it "off".
6.2 ChangeOfTopic
DEFINE ACTION ChangeOfTopic
ON TOPIC "input2/topic" DO
    PUBLISH TOPIC "input2/topic" WITH (PAYLOAD + 1)
- Trigger: A message is published to "input2/topic".
- Logic:
- Whatever the PAYLOADis (assuming it's numeric), increment it by 1, then publish the new value back to the same topic.
6.3 SHOWTIMEEVERY5SECONDS
DEFINE ACTION SHOWTIMEEVERY5SECONDS
ON EVERY 5 SECONDS DO
    PUBLISH TOPIC "input2/topic" WITH TIMESTAMP "UTC"
- Trigger: Every 5 seconds.
- Logic:
- Publish the current UTC time to "input2/topic".
6.4 CheckIfPar
DEFINE ACTION CheckIfPar
ON EVERY 1 MINUTE DO
    IF (GET TOPIC "input2/topic" % 2) EQUALS 0 THEN
        PUBLISH TOPIC "teste" WITH "pair"
    ELSE
        PUBLISH TOPIC "teste" WITH "odd"
- Trigger: Every 1 minute.
- Logic:
- Checks the value of input2/topic.
- If that value is even (% 2 EQUALS 0), publish"pair"toteste. Otherwise, publish"odd".
7. Adding or Removing Actions
To add an Action in Coreflux, you publish its entire DEFINE ACTION snippet to the special system topic "$SYS/Coreflux/Command", using the parameter -addAction.
Example: Add StrokeGenerator:
Topic: $SYS/Coreflux/Command
Payload:
publish -addAction 
DEFINE ACTION StrokeGenerator
ON EVERY 5 SECONDS DO
    IF GET TOPIC "Coreflux/Porto/MeetingRoom/Light1/command/switch:0" EQUALS "off" THEN
        PUBLISH ...
    ...
Once accepted, the broker will store and run this Action. You can confirm it by checking "$SYS/Coreflux/Actions".
Removing Actions
Similarly, to remove an existing Action, publish to the same system topic with -removeAction <ActionName>:
8. Important
- Indentation clarifies logic blocks and nested statements.
- Expressions let you retrieve topic payloads, do math, and compare values.
- IF THEN ELSE controls logic flow based on your conditions.
- PAYLOAD references incoming data; TIMESTAMP injects the current time.
- Events can be triggered by time intervals (ON EVERY) or by topic messages (ON TOPIC).
With these fundamentals, you can create custom Actions to automate logic within the Coreflux broker using LOT.
How LOT Actions Work
LOT Actions within Coreflux operate on two primary triggering mechanisms and follow a specific execution model designed for real-time IoT environments.
Action Triggers
Actions can be triggered in two ways:
graph TB
    subgraph "Action Trigger Mechanisms"
        A[LOT Action] --> B{Trigger Type}
        B -->|Time-based| C[Scheduled Execution]
        B -->|Topic-based| D[Event-driven Execution]
    end
    subgraph "Time-based Execution"
        C --> C1[System checks every second]
        C1 --> C2[Compares current time with\naction's scheduled time]
        C2 --> C3[Executes if time condition met]
        C3 --> C4[Updates timestamp for\nnext execution]
    end
    subgraph "Topic-based Execution"
        D --> D1[Monitor subscribed topics]
        D1 --> D2[Topic published]
        D2 --> D3[Immediately execute action]
    endTime-based Triggers
Time-based actions function on a scheduled basis (every minute, hour, day, week, or month):
- The Coreflux system maintains a task that runs every second
- This task checks all time-based actions to determine if they need to be executed
- Each action has a timestamp based on its previous execution
- When the scheduled time is reached, the action is triggered
- After execution, the timestamp is updated for the next scheduled run
For example, an action scheduled to run every hour will be checked by the system each second, but will only execute when the hour interval has elapsed since its last execution.
Topic-based Triggers
Topic-based actions are event-driven and execute in response to MQTT messages:
- These actions monitor specific topics
- When a message is published to a monitored topic, the action is triggered immediately
- This allows for real-time response to events in the system
- Topic-based actions can create chains of execution, where one action's output triggers another action
Action Execution Model
LOT Actions follow a Programmable Logic Controller (PLC)-like execution model:
sequenceDiagram
    participant Topic System
    participant Action Engine
    participant Action Logic
    Note over Topic System,Action Logic: Execution Flow
    Topic System->>Action Engine: Trigger (time or topic)
    Action Engine->>Topic System: Take snapshot of relevant topics
    Action Engine->>Action Logic: Process with inputs from snapshot
    Action Logic->>Action Engine: Return results
    Action Engine->>Topic System: Publish output topics
    Note over Topic System: Other actions may be triggered by outputsThe execution process works as follows:
- 
Input Snapshot: When an action is triggered, the system takes a "snapshot" of all topics relevant to the action, capturing their current state. 
- 
Processing: The action executes using the input snapshot, ensuring it works with a consistent view of the system state at the time it was triggered. 
- 
Output Flush: After execution completes, the action "flushes" its outputs by publishing to the defined topics. 
- 
Cascading Actions: These output topics may trigger other actions, creating a cascading flow of operations. 
This execution model ensures deterministic behavior and allows for complex event processing chains while maintaining system stability.
graph LR
    subgraph "Action Execution"
        A[Trigger] --> B[Input Snapshot]
        B --> C[Process Logic]
        C --> D[Output Flush]
        D --> E[Potential Cascade]
    end
    subgraph "Input Sources"
        F1[Topic A] --> B
        F2[Topic B] --> B
        F3[System State] --> B
    end
    subgraph "Output Destinations"
        D --> G1[Topic X]
        D --> G2[Topic Y]
    end
    G1 --> H[Another Action]This approach enables sophisticated automation workflows where actions can be sequenced, conditional operations can be performed, and complex event processing chains can be established.
Rules and Command Processing
While Actions handle event processing and automation, Rules govern permissions and system operations. Rules are triggered when specific operations are requested, controlling whether those operations are allowed to proceed.
graph TB
    A[Command] --> B{CommandCall Rule}
    B -->|Approved| C{Specific Rule}
    B -->|Rejected| D[Command Denied]
    C -->|Approved| E[Command Executed]
    C -->|Rejected| DThe command processing flow:
- Any command first passes through the CommandCallrule
- If approved, it then passes to the specific rule type for that command
- Only if both rules approve will the command execute
Common rule types include:
| Rule Category | Examples | 
|---|---|
| Topic Access | Subscribe,SubscribeSys,Publish,PublishSys | 
| User Management | UserManagementCreation,UserManagementPasswordChange,UserManagementUpdate,UserManagementRemove | 
| Asset Management | AssetManagementCreation,AssetManagementRemove,AssetManagementStart | 
| Action Management | ActionManagementCreation,ActionManagementRemove,ActionManagementRun | 
| Rule Management | RuleManagementCreation,RuleManagementRemove | 
| Model Management | ModelManagementCreation,ModelManagementRemove | 
| Route Management | RouteManagementCreation,RouteManagementRemove | 
| System | SystemConfiguration,CommandCall,ShellCommand | 
This rule hierarchy ensures that system operations follow proper authorization protocols and helps maintain system security and integrity.