Skip to content

PUBLISH MODEL Functional Keyword

Feature Since Version Notes
PUBLISH MODEL >v1.6.0 Publishes structured data using predefined models

Overview

  • Description: Publishes structured JSON data to an MQTT topic using a predefined model schema. This command is used within ACTION blocks to create consistent, well-formed JSON payloads without manual string construction. It combines event-driven logic with structured data models.

Signature

  • Syntax:
    PUBLISH MODEL <ModelName> TO "<topicPath>" WITH
        fieldName1 = <value1>
        fieldName2 = <value2>
        ...
    

Parameters

  • <ModelName>: The name of a previously defined model (using DEFINE MODEL ... COLLAPSED)
  • "<topicPath>": The MQTT topic where the JSON payload will be published
  • fieldName = <value>: Field assignments matching the model's defined fields

Prerequisites

Before using PUBLISH MODEL, you must define a model with the COLLAPSED keyword:

DEFINE MODEL <ModelName> COLLAPSED
    ADD <FIELD_TYPE> "<field_name>"
    ADD <FIELD_TYPE> "<field_name>"
    ...

Key Points: - COLLAPSED means the model has no WITH TOPIC - it's a template, not an automatic trigger - Models used with PUBLISH MODEL are schemas/templates for structured data - Field types include: STRING, INT, DOUBLE, BOOL, OBJECT, ARRAY

Field Value Sources

1. Direct Literals

PUBLISH MODEL MyModel TO "output/topic" WITH
    status = "ACTIVE"
    count = 100
    enabled = TRUE

2. Action Variables

SET "sensor_id" WITH TOPIC POSITION 1
PUBLISH MODEL MyModel TO "output/topic" WITH
    sensor_id = {sensor_id}

3. JSON Extraction with GET JSON

PUBLISH MODEL MyModel TO "output/topic" WITH
    temperature = (GET JSON "temperature" IN PAYLOAD AS DOUBLE)
    sensor_name = (GET JSON "name" IN PAYLOAD AS STRING)

4. Topic Data with GET TOPIC

PUBLISH MODEL MyModel TO "output/topic" WITH
    status = GET TOPIC "system/current/status"
    last_value = GET TOPIC "sensors/last/reading"

5. Calculations and Expressions

PUBLISH MODEL MyModel TO "output/topic" WITH
    efficiency = ({produced} / {target} * 100)
    total = ({passed} + {failed})

6. Timestamps

PUBLISH MODEL MyModel TO "output/topic" WITH
    timestamp = TIMESTAMP "UTC"
    unix_time = TIMESTAMP "UNIX"

Note: Within PUBLISH MODEL field assignments, TIMESTAMP uses the format TIMESTAMP "format" (without the WITH keyword). This is different from standalone usage where TIMESTAMP WITH "format" is required.

7. Conditional Values

PUBLISH MODEL MyModel TO "output/topic" WITH
    priority = IF {severity} EQUALS "HIGH" THEN 1 ELSE 2
    status = IF {count} > 100 THEN "FULL" ELSE "OK"

8. Nested Objects

PUBLISH MODEL MyModel TO "output/topic" WITH
    metadata = {
        "source": {sensor_id},
        "quality": {quality_score},
        "validated": TRUE
    }

Usage Examples

Basic Example: Simple Sensor Record

DEFINE MODEL SensorRecord COLLAPSED
    ADD STRING "sensor_id"
    ADD DOUBLE "temperature"
    ADD STRING "timestamp"

DEFINE ACTION LogSensorData
ON TOPIC "sensors/+/data" DO
    SET "sensor_id" WITH TOPIC POSITION 1

    PUBLISH MODEL SensorRecord TO "sensors/processed/" + {sensor_id} WITH
        sensor_id = {sensor_id}
        temperature = PAYLOAD
        timestamp = TIMESTAMP "UTC"

Test:

Publish to: sensors/temp001/data
Payload: 25.5

Result in: sensors/processed/temp001
{
  "sensor_id": "temp001",
  "temperature": 25.5,
  "timestamp": "2025-10-25T14:30:15Z"
}

Intermediate Example: JSON Data Extraction

DEFINE MODEL SensorDataRecord COLLAPSED
    ADD STRING "sensor_id"
    ADD STRING "sensor_type"
    ADD DOUBLE "temperature"
    ADD DOUBLE "pressure"
    ADD STRING "timestamp"
    ADD STRING "quality_status"

DEFINE ACTION ProcessSensorJSON
ON TOPIC "sensors/+/json_data" DO
    SET "sensor_id" WITH TOPIC POSITION 1

    // Extract data from JSON payload using GET JSON
    SET "temperature_val" WITH (GET JSON "temperature" IN PAYLOAD AS DOUBLE)
    SET "pressure_val" WITH (GET JSON "pressure" IN PAYLOAD AS DOUBLE)
    SET "sensor_type" WITH (GET JSON "type" IN PAYLOAD AS STRING)
    SET "quality" WITH (GET JSON "quality_status" IN PAYLOAD AS STRING)

    // Publish structured sensor record
    PUBLISH MODEL SensorDataRecord TO "sensors/processed/" + {sensor_id} WITH
        sensor_id = {sensor_id}
        sensor_type = {sensor_type}
        temperature = {temperature_val}
        pressure = {pressure_val}
        timestamp = TIMESTAMP "UTC"
        quality_status = {quality}

Test:

Publish to: sensors/temp001/json_data
Payload: {
  "temperature": 75.5,
  "pressure": 101.3,
  "type": "environmental",
  "quality_status": "GOOD"
}

Result in: sensors/processed/temp001
{
  "sensor_id": "temp001",
  "sensor_type": "environmental",
  "temperature": 75.5,
  "pressure": 101.3,
  "timestamp": "2025-10-25T14:30:15Z",
  "quality_status": "GOOD"
}

Advanced Example: Alarm Generation

DEFINE MODEL AlarmRecord COLLAPSED
    ADD STRING "alarm_id"
    ADD STRING "equipment_id"
    ADD STRING "alarm_type"
    ADD DOUBLE "trigger_value"
    ADD DOUBLE "threshold"
    ADD STRING "severity"
    ADD STRING "message"
    ADD STRING "timestamp"
    ADD BOOL "auto_generated"

DEFINE ACTION JSONAlarmProcessor
ON TOPIC "alarms/+/json_input" DO
    SET "equipment_id" WITH TOPIC POSITION 1

    // Extract alarm data from JSON payload
    SET "alarm_type" WITH (GET JSON "alarm_type" IN PAYLOAD AS STRING)
    SET "current_value" WITH (GET JSON "current_value" IN PAYLOAD AS DOUBLE)
    SET "threshold_value" WITH (GET JSON "threshold" IN PAYLOAD AS DOUBLE)
    SET "severity_level" WITH (GET JSON "severity" IN PAYLOAD AS STRING)
    SET "alarm_message" WITH (GET JSON "message" IN PAYLOAD AS STRING)

    // Generate structured alarm record
    PUBLISH MODEL AlarmRecord TO "alarms/structured/" + {equipment_id} WITH
        alarm_id = (RANDOM UUID)
        equipment_id = {equipment_id}
        alarm_type = {alarm_type}
        trigger_value = {current_value}
        threshold = {threshold_value}
        severity = {severity_level}
        message = {alarm_message}
        timestamp = TIMESTAMP "UTC"
        auto_generated = TRUE

    // Route based on severity
    IF {severity_level} EQUALS "CRITICAL" THEN
        PUBLISH TOPIC "alarms/critical/" + {equipment_id} WITH {alarm_message}

Differences from Basic Models

Aspect Basic Model (WITH TOPIC) Action Model (COLLAPSED)
Definition DEFINE MODEL Name WITH TOPIC "..." DEFINE MODEL Name COLLAPSED
Trigger Automatic on topic changes Manual via PUBLISH MODEL in actions
Control Triggered by field marked AS TRIGGER Full control in action logic
When to Use Automatic data transformation pipelines Event-driven, conditional data creation

GET JSON - Extracting JSON Data

GET JSON is commonly used with PUBLISH MODEL to extract fields from JSON payloads:

Syntax

GET JSON "<field_name>" IN <source> AS <TYPE>

Parameters

  • <field_name>: The JSON field to extract (supports dot notation for nested fields)
  • <source>: Usually PAYLOAD or a {variable} containing JSON
  • <TYPE>: One of STRING, INT, DOUBLE, BOOL

Examples

Simple field:

SET "name" WITH (GET JSON "sensor_name" IN PAYLOAD AS STRING)

Nested field:

SET "temp" WITH (GET JSON "data.sensors.temperature" IN PAYLOAD AS DOUBLE)

From variable:

SET "json_data" WITH GET TOPIC "config/settings"
SET "threshold" WITH (GET JSON "limits.max" IN {json_data} AS DOUBLE)

Best Practices

1. Always Use Type Casting with GET JSON

Correct:

SET "temp" WITH (GET JSON "temperature" IN PAYLOAD AS DOUBLE)

Incorrect:

SET "temp" WITH (GET JSON "temperature" IN PAYLOAD)

2. Use COLLAPSED for Action Models

Correct:

DEFINE MODEL MyModel COLLAPSED
    ADD STRING "field"

Incorrect:

DEFINE MODEL MyModel WITH TOPIC "some/topic" COLLAPSED
    ADD STRING "field"

3. Validate Extracted Data

SET "value" WITH (GET JSON "value" IN PAYLOAD AS DOUBLE)
IF {value} < 0 OR {value} > 100 THEN
    PUBLISH TOPIC "errors/validation" WITH "Invalid value: " + {value}
ELSE
    PUBLISH MODEL ValidatedData TO "processed/data" WITH
        value = {value}
        validated = TRUE

4. Handle Missing JSON Fields

SET "optional_field" WITH (GET JSON "optional" IN PAYLOAD AS STRING)
IF {optional_field} EQUALS EMPTY THEN
    SET "optional_field" WITH "DEFAULT_VALUE"

Use Cases

Event Logging

Create structured log entries when specific events occur: - Equipment state changes - Production milestones - Alarm occurrences - User actions

Data Transformation

Convert raw data into standardized formats: - JSON to structured records - Multiple sources to single record - Unit conversions and calculations - Data enrichment

Report Generation

Build reports when conditions are met: - Shift summaries - Quality reports - Performance analyses - Compliance records

Alarm Management

Generate standardized alarms from various triggers: - Threshold violations - State changes - Error conditions - Maintenance alerts

Integration with Python

Combine PUBLISH MODEL with Python for advanced processing:

# Script Name: DataProcessor
def validate_and_enrich(json_data):
    import json
    data = json.loads(json_data)

    # Validation logic
    if data.get('temperature', 0) < 0:
        return {"error": "Invalid temperature", "valid": False}

    # Enrichment
    data['validated'] = True
    data['quality_score'] = calculate_quality(data)

    return json.dumps(data)
DEFINE MODEL ProcessedSensorData COLLAPSED
    ADD STRING "sensor_id"
    ADD DOUBLE "temperature"
    ADD DOUBLE "quality_score"
    ADD BOOL "validated"
    ADD STRING "timestamp"

DEFINE ACTION PythonModelIntegration
ON TOPIC "sensors/+/raw" DO
    SET "sensor_id" WITH TOPIC POSITION 1

    CALL PYTHON "DataProcessor.validate_and_enrich"
        WITH (PAYLOAD)
        RETURN AS {processed}

    PUBLISH MODEL ProcessedSensorData TO "sensors/processed/" + {sensor_id} WITH
        sensor_id = {sensor_id}
        temperature = (GET JSON "temperature" IN {processed} AS DOUBLE)
        quality_score = (GET JSON "quality_score" IN {processed} AS DOUBLE)
        validated = (GET JSON "validated" IN {processed} AS BOOL)
        timestamp = TIMESTAMP "UTC"

Important Syntax Notes

TIMESTAMP in PUBLISH MODEL

Within PUBLISH MODEL field assignments, TIMESTAMP has a special syntax:

Correct (in PUBLISH MODEL):

PUBLISH MODEL MyModel TO "topic" WITH
    timestamp = TIMESTAMP "UTC"

Incorrect (in PUBLISH MODEL):

PUBLISH MODEL MyModel TO "topic" WITH
    timestamp = TIMESTAMP WITH "UTC"  // Don't use WITH here

Compare to standalone usage:

// Outside PUBLISH MODEL, use WITH:
PUBLISH TOPIC "time" WITH TIMESTAMP WITH "UTC"
ADD "timestamp" WITH TIMESTAMP WITH "UTC"

// Inside PUBLISH MODEL, don't use WITH:
PUBLISH MODEL MyModel TO "topic" WITH
    timestamp = TIMESTAMP "UTC"

Notes & Additional Information

  • PUBLISH MODEL creates JSON output automatically - no manual JSON string construction needed
  • All field names must match those defined in the model
  • Field values can be any valid LOT expression
  • The resulting JSON is published to the specified topic
  • TIMESTAMP syntax within field assignments is TIMESTAMP "format" (without WITH)
  • Use with database routes to store structured data in OpenSearch, MongoDB, PostgreSQL, etc.