HiveMQ Edge Protocol Adapters

HiveMQ Edge protocol adapters facilitate communication between systems, devices, or networks that use different proprietary or incompatible communication protocol formats. Once connected, the protocol adapter converts received data into open standards MQTT messages that are published to your local MQTT broker.

HiveMQ Edge offers numerous pre-built protocol adapters and the ability to create custom protocol adapters to suit your business needs.

The following HiveMQ Edge protocol adapters sre currently available:

Additional HiveMQ Edge protocol adapters will be added to the project over time.

Tags in Protocol Adapters

The functionality and configuration of industry protocols differ significantly. HiveMQ Edge enables the use of protocol tags to minimize configuration complexity to simplify integration and enhance ease of use. The tag abstracts the usages of the data points a protocol adapter provides. Instead of dealing complex protocol-specific identifiers, users can interact with human-readable tags. For example, although configuring Modbus registers is very different from setting up node IDs in OPC UA, all HiveMQ Edge protocol adapters use MQTT destination topics as a common endpoint for data routing.

Managing Tags

To define a tag on the HiveMQ Edge workspace, simply select a device:

Edit Tags from Workspace

A standardized dialog that is similar for every protocol adapter opens. The first part of the tag definition includes the name of the tag and a description. The tag name must be unique across the HiveMQ Edge deployment. The definition part of the tag varies based on the protocol adapter type. For example, a OPC UA tag:

Editing Tags (Example OPCUA

Northbound

In edge computing, northbound refers to the flow of data or communication from edge devices or lower layers of infrastructure to higher layers in a computing or network hierarchy. Northbound communication typically involves sending processed data, insights, or alerts from the edge layer to centralized systems for storage, further analysis, or integration with other systems.

  1. northboundMappings parameters

Property Name

Default

Mandatory

Description

Format

tagName

The tag name.

String (Tags). For example, machine_EFIS10/temperature.

topic

The MQTT topic.

String. For example, machine/EFIS10/temperature

maxQos

1

The maximum MQTT QoS for the outgoing messages.

Possible values are 0,1, or 2.

includeTagNames

false

Include the tag name in the MQTT payload.

Boolean.

includeTimestamp

true

Include a timestamp in the MQTT payload.

Boolean.

messageExpiryInterval

no expiry

The message expiry interval in seconds for MQTT 5 messages.

Long > 0.

mqttUserProperties

List of user properties to include in the MQTT message.

List of MQTT user properties.

Southbound

In edge computing, southbound refers the flow of data or communication from higher layers of infrastructure down to components that are located closer to the edge of the network. Southbound communication is typically used to send commands, configurations, policies, updates, or control signals from a centralized system.

Table 1. southboundMappings parameters
Property Name Default Mandatory Description Format

tagName

The tag name

String (Tags). For example, machine_EFIS10/temperature

topicFilter

The MQTT topic filter to read from

String. For example, machine/+/temperature

Northbound and southbound tag schemas

From version 2026.13, a tag exposes two JSON schemas rather than one, so each consumer gets the schema appropriate to its direction:

Northbound (read)

The shape of what the device publishes: an envelope carrying tagName and timestamp around the tag’s value, plus metadata and context when the adapter supplies them.

Southbound (write)

The shape of what you may write to the device: value alone, with the rest of the envelope dropped.

The two documents for one OPC UA condition tag, abridged
// northbound: GET .../schema/melocoton/boiler-high-temp
{"type": "object",
 "properties": {"tagName":   {"type": "string",  "readOnly": true},
                "timestamp": {"type": "integer", "readOnly": true},
                "value":     {"type": "object", "readOnly": true,
                              "properties": { /* the alarm's 60 fields */ }}},
 "required": ["value"], "readOnly": true}

// southbound: GET .../schema/melocoton/boiler-high-temp?direction=SOUTHBOUND
{"type": "object",
 "properties": {"value": {"type": "object",
                          "properties": {"method": {"type": "string", "writeOnly": true},
                                         "eventId": {"type": "string", "writeOnly": true},
                                         "comment": {"type": ["string", "null"], "writeOnly": true}},
                          "required": ["method"],
                          "writeOnly": true}},
 "required": ["value"]}
value stays in the southbound document and stays required, so a southbound mapping must write into $.value.…, not into the root. Only the read-only envelope around it is dropped.

For an ordinary tag, the southbound document is simply that envelope removed. Nothing is invented and nothing is renamed:

// southbound schema of a plain integer tag
{"type": "object",
 "properties": {"value": {"type": "integer", "minimum": -2147483648, "maximum": 2147483647}},
 "required": ["value"]}

Before the split, a single schema served both directions, wrapped in the read-only envelope. A southbound mapping editor was fed that schema, and most of its fields can never be written. tagName, timestamp and metadata each had to be marked unusable one by one. A write form is now built from a schema that describes writing.

For most tags the southbound schema is the northbound one with the envelope removed. An adapter can supply a different southbound schema when the write shape is not a projection of the read shape. The OPC UA event tag kinds are the current examples. A condition tag publishes an alarm transition and accepts a command. A refresh tag accepts {"method": "REFRESH"}. An event subscription tag publishes a southbound schema that accepts nothing at all. See OPC UA Alarms and Conditions.

Read-only members inside the value are deliberately kept in the southbound schema rather than removed from it. Per-field write permission cannot be stated correctly by a static JSON schema: an array whose items were read-only would admit only the empty array, and a required read-only member would make the document impossible to satisfy. The members therefore stay and carry a readOnly annotation, and each consumer decides what to offer as a write destination. Only the non-writable envelope is dropped.

readOnly is descriptive metadata, not an assertion. It is a JSON Schema annotation, and no HiveMQ Edge runtime currently rejects a write because it carries a field marked readOnly. Use it to decide what to offer as a write destination, not as a safety boundary.

The southbound schema is not only a user interface concern. When a southbound mapping starts, the tag’s southbound schema is registered with Data Hub. It is applied by the Serdes.serialize step of the generated data policy, so it is the structural validation contract for the write path. A transformed message that does not satisfy it fails the pipeline and never reaches the device. Member names, types, required members and declared ranges are enforced there. readOnly is not.

Requesting a direction

The tag schema endpoint takes an optional direction query parameter:

GET /api/v1/management/protocol-adapters/schema/{adapterId}/{tagName}?direction=SOUTHBOUND

direction is NORTHBOUND or SOUTHBOUND, spelled in upper case. The value is matched exactly, so direction=southbound is not accepted. Omitting the parameter returns the northbound schema, so an existing caller keeps both the URL and the behaviour it had. An unrecognised value is answered with 400 Bad Request rather than falling back to a default, because handing a mistyped caller the wrong document silently is worse than failing.

Requesting both directions for one tag
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/authenticate \
  -H 'Content-Type: application/json' \
  -d '{"userName":"admin","password":"hivemq"}' | jq -r .token)

# northbound (read), the default
curl -s -H "Authorization: Bearer $TOKEN" \
  'http://localhost:8080/api/v1/management/protocol-adapters/schema/my-adapter/my-tag'

# southbound (write)
curl -s -H "Authorization: Bearer $TOKEN" \
  'http://localhost:8080/api/v1/management/protocol-adapters/schema/my-adapter/my-tag?direction=SOUTHBOUND'
The tag name is a path segment, so a tag whose name contains / must be URL-encoded. For example, boiler/temperature becomes boiler%2Ftemperature.

The earlier writing-schema endpoint is deprecated and answers with 301 Moved Permanently, whose Location header carries the replacement with direction=SOUTHBOUND:

GET /api/v1/management/protocol-adapters/writing-schema/{adapterId}/{tagName}

A client that follows redirects keeps working without a change of URL, and now receives the southbound schema rather than the combined document this endpoint used to return.

Adapter authors should note that the adapter SDK’s writeSchema() accessor has been removed in favour of southboundSchema().

Topic Filters

MQTT topic filters are used to read data that is subsequently written to a tag. To ensure reliable operation, the topic filter must have a data schema.

Currently, only JSON schemas are supported.

Topic filters can be defined on the HiveMQ Edge workspace:

Edit Topic Filters from Workspace

A dialog to create topic filters and associate a schema automatically opens:

Topic Filter Dialog from Workspace

Once a topic filter is created, there are two ways to assign a schema:

  1. If you are already sending data to a topic that is included in the topic filter, the topic filter dialog gives you the option to infer a schema from existing traffic.

    Infer a schema from existing traffic

  2. Upload a JSON Schema file to HiveMQ Edge that defines the schema of the incoming data.

The JSON Schema must include at least a properties definition. For more information, see JSON Schema definition.
Example JSON Schema for southbound traffic to control the speed of a motor
{
  "title": "The schemas defines the data structure for controlling speed",
  "type": "object",
  "properties": {
    "speed": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    }
  },
  "required": [ "speed" ]
}

The example JSON Schema includes a speed property that is an integer and ranges from 0 to 100.

Example JSON southbound payload
{
  "speed": 50
}

HiveMQ Edge makes sure that the incoming MQTT traffic is continuously checked against the defined schema before it writes to the tag and eventually to the device. A message that the schema rejects is published again to the topic $invalid/<original topic>, with its original payload and QoS level. A message that the device write itself rejects is dropped and logged, and is not published to the $invalid topic.

HiveMQ Edge Protocol Adapter Configuration

Adapter instances can be added to the system using the HiveMQ Edge API, user interface, or a static configuration. All three methods result in the main config.xml file being updated with a new element within the <protocol-adapters> element. Each adapter type has its own element name that matches the adapter type name in the ProtocolAdapterFactory. For example, the Simulation protocol has a type of simulation and a <simulation></simulation> configuration element.

In the adapter configuration, each adapter instance much be identified with a unique <id> element .

The HiveMQ Edge UI and API automatically validate the uniqueness of the instance.

Simulation Adapter

The simulation adapter enables the system to be configured to publish messages with random values through the protocol adapter layer at a specific interval. This functionality gives you the ability to test and observe the behavior of adapters in your system without requiring actual hardware or external data sources.

The adapter supports the following capabilities:

  • Read (Northbound): Generate simulated data and publish to MQTT topics.

  • Write (Southbound): Accept values from MQTT topics for tags with a static value.

  • Combine: Use simulated values in data combining.

The example configuration publishes random data with MQTT quality of service level 0 to the destination topic sim.

Example simulation adapter configuration
<protocol-adapters>
    <protocol-adapter>
        <adapterId>sim</adapterId>
        <protocolId>simulation</protocolId>
        <config>
          <minDelay>0</minDelay>
          <maxDelay>0</maxDelay>
          <minValue>0</minValue>
          <maxValue>1000</maxValue>
            <simulationToMqtt>
                <pollingIntervalMillis>100</pollingIntervalMillis>
                <maxPollingErrorsBeforeRemoval>-1</maxPollingErrorsBeforeRemoval>
            </simulationToMqtt>
        </config>
        <northboundMappings>
            <northboundMapping>
                <topic>sim</topic>
                <includeTagNames>false</includeTagNames>
                <includeTimestamp>true</includeTimestamp>
                <maxQos>0</maxQos>
                <tagName>t1</tagName>
            </northboundMapping>
        </northboundMappings>
    </protocol-adapter>
</protocol-adapters>

Simulation Adapter Properties

Table 2. Simulation Adapter Properties (config)
Property Name Default Mandatory Description Format

id

The unique identifier of the selected adapter instance.

String [a-zA-Z0-9-_]

minValue

0

Minimum limit for the randomly generated values (inclusive).

Integer >= 0

maxValue

1000

Maximum limit for the randomly generated values (exclusive).

Integer

minDelay

0

Minimum artificial delay in milliseconds before the polling method generates a value. Must not exceed maxDelay.

Integer >= 0

maxDelay

0

Maximum artificial delay in milliseconds before the polling method generates a value. When minDelay equals maxDelay, the delay is fixed; otherwise, a random delay between minDelay and maxDelay is used.

Integer >= 0

simulationToMqtt

Configuration for polling and MQTT publishing

simulationToMqtt

Table 3. Simulation To MQTT (simulationToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles. Each cycle generates new random values for all configured tags.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries.

Integer >= -1

Table 4. Simulation To MQTT Mapping
Property Name Default Mandatory Description Format

common configurations

Common configurations

See Common Configurations

Simulation Adapter Tags

A tag of the simulation adapter defines which value the adapter emits for that tag. The definition of a tag holds one of the following elements, or none.

Table 5. Simulation Adapter Tag Definition (definition)
Element Description Properties

randomValue

The tag emits a random number in a range of its own on every polling cycle.

valueType: INT, LONG, or DOUBLE. minValue and maxValue: the range of the generated value. minValue must be less than maxValue. Set all three properties. The UI requires them, while a configuration file that omits minValue or maxValue uses 0 for the missing one.

staticValue

The tag emits the same typed value on every polling cycle. A static value tag accepts southbound writes. A written value replaces the emitted value until the adapter restarts, and the configured value is unchanged.

valueType: INT, LONG, DOUBLE, or STRING. value: the value as a string, converted to valueType. Both properties are required.

A tag definition without either element emits a random double between the minValue and the maxValue of the adapter. A definition with both elements is rejected. Only tags with a staticValue accept southbound writes. A write to any other tag of the simulation adapter fails.

Example simulation adapter tags
<tags>
    <tag>
        <name>t1</name>
        <description>Random temperature</description>
        <definition>
            <randomValue>
                <valueType>DOUBLE</valueType>
                <minValue>18</minValue>
                <maxValue>25</maxValue>
            </randomValue>
        </definition>
    </tag>
    <tag>
        <name>t2</name>
        <description>Set point</description>
        <definition>
            <staticValue>
                <valueType>INT</valueType>
                <value>42</value>
            </staticValue>
        </definition>
    </tag>
</tags>
Example MQTT Payload of the Simulation Adapter
{
  "timestamp": 1730707250320,
  "value": 729.6615064364747
}

The payload includes:

  • timestamp: Unix timestamp in milliseconds when the value was generated (only present if includeTimestamp is true).

  • value: Randomly generated double-precision floating-point number between minValue (inclusive) and maxValue (exclusive).

The Simulation adapter publishes a new value on every polling cycle. Unlike some other adapters, there is no option to publish only when the value changes, as the adapter generates new random values each time.

ModBus (TCP) Adapter

The ModBus adapter enables connections to ModBus slaves via TCP. The adapter supports reading from coils, discrete inputs, input registers, and holding registers in the address range 0-65534 (incl).

The adapter supports the following capabilities:

  • Read (Northbound): Poll Modbus registers and publish data to MQTT topics.

The connection samples the ModBus slave on the sampling time specified in the configuration. Each connection can be configured to only publish samples when changes in values are detected (publishChangedDataOnly).

Example ModBus (TCP) adapter configuration
<modbus>
    <id>my-modbus-protocol-adapter</id>
    <host>my.modbus-server.com</host>
    <port>502</port>
    <timeoutMillis>500</timeoutMillis>
    <modbusToMqtt>
        <pollingIntervalMillis>150</pollingIntervalMillis>
        <maxPollingErrorsBeforeRemoval>5</maxPollingErrorsBeforeRemoval>
        <publishChangedDataOnly>false</publishChangedDataOnly>
        <modbusToMqttMappings>
            <modbusToMqttMapping>
                <mqttTopic>my/topic</mqttTopic>
                <mqttQos>1</mqttQos>
                <tagName>myTag</tagName>
                <messageHandlingOptions>MQTTMessagePerSubscription</messageHandlingOptions>
                <mqttUserProperties>
                    <mqttUserProperty>
                        <name>name</name>
                        <value>value1</value>
                    </mqttUserProperty>
                    <mqttUserProperty>
                        <name>name</name>
                        <value>value2</value>
                    </mqttUserProperty>
                </mqttUserProperties>
                <includeTagNames>true</includeTagNames>
                <includeTimestamp>false</includeTimestamp>
            </modbusToMqttMapping>
        </modbusToMqttMappings>
    </modbusToMqtt>
</modbus>
Example ModBus (TCP) tag definition referenced via its name myTag in the config above
<tag>
    <tagDefinition>
        <unitId>0</unitId>
        <startIdx>11</startIdx>
        <readType>HOLDING_REGISTERS</readType>
        <dataType>INT_64</dataType>
    </tagDefinition>
    <tagName>myTag</tagName>
</tag>

ModBus (TCP) Adapter Properties

Table 6. ModBus Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

id

The unique identifier of the selected adapter instance.

String [a-zA-Z0-9-_]

host

The host or IPv4/IPv6 of the ModBus device.

Hostname or IP

port

The port to connect to.

Integer 1-65535

timeoutMillis

5000

Time in milliseconds to await a connection before the client gives up.

Integer (1000-15000)

modbusToMqtt

Configuration for Modbus to MQTT data flow

modbusToMqtt

Table 7. ModBus to MQTT (modbusToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries.

Integer >= -1

publishChangedDataOnly

true

When enabled, the adapter only publishes data when a value has changed since the last poll. This reduces MQTT traffic for slow-changing data.

Boolean

ModBus Tag Definition

Tags in the Modbus adapter define which registers to read from the device.

Table 8. ModBus Tag Definition Properties
Property Name Default Mandatory Description Format

startIdx

The starting address index (inclusive) of the register to read.

Integer (0-65535)

readType

Type of Modbus register to read.

COILS, DISCRETE_INPUTS, INPUT_REGISTERS, HOLDING_REGISTERS

unitId

Id of the unit (slave) to access on the Modbus network.

Integer

dataType

INT_16

Defines how the read registers are interpreted.

See Data Types

flipRegisters

false

When enabled, registers are evaluated in reverse order. Some Modbus implementations write content as big endian but order registers as little endian.

Boolean

Modbus Register Types

  • COILS: 1-bit read/write registers (function codes 1/5/15)

  • DISCRETE_INPUTS: 1-bit read-only inputs (function code 2)

  • INPUT_REGISTERS: 16-bit read-only registers (function code 4)

  • HOLDING_REGISTERS: 16-bit read/write registers (function codes 3/6/16)

ModBus Data Types

Table 9. Supported Modbus Data Types
Type Description Size

BOOL

Boolean value

1 bit / 1 register

INT_16

Signed 16-bit integer

16 bit / 1 register

UINT_16

Unsigned 16-bit integer

16 bit / 1 register

INT_32

Signed 32-bit integer

32 bit / 2 registers

UINT_32

Unsigned 32-bit integer

32 bit / 2 registers

INT_64

Signed 64-bit integer

64 bit / 4 registers

FLOAT_32

32-bit floating-point (IEEE 754 single precision)

32 bit / 2 registers

FLOAT_64

64-bit floating-point (IEEE 754 double precision)

64 bit / 4 registers

UTF_8

UTF-8 encoded string

64 bit / 4 registers

For multi-register data types (INT_32, INT_64, FLOAT_32, FLOAT_64, UTF_8), use the flipRegisters option if your device uses little-endian register ordering.
Each sample is published as an array with each 16-bit index encoded as a 2-octet decimal value.

OPC UA Adapter

The OPC UA adapter enables connections to OPC UA servers. You can configure the adapter to read from an OPC UA server and publish to an MQTT topic (opcuaToMqtt) or write to an OPC UA server from an MQTT topic (mqttToOpcua).

Both directions require basic connectivity information for OPC UA to be configured.

The OPC UA adapter supports the following capabilities:

  • Read (Northbound): Subscribe to OPC UA nodes and publish data to MQTT topics.

  • Write (Southbound): Write data from MQTT messages to OPC UA nodes.

  • Discover: Browse and discover available nodes on the OPC UA server.

  • Bidirectional: Combine northbound and southbound operations simultaneously.

The connection creates subscriptions with the OPC UA server and discovers available nodes on the server.

Unlike some other protocol adapters, the OPC UA adapter does not filter unchanged values. Every data notification received from the OPC UA server is published to MQTT, even if the value has not changed since the last notification. This behavior is inherent to the OPC UA subscription model, where the server determines when to send notifications based on the configured publishing interval and server queue settings.
Example minimal OPC UA adapter configuration (anonymous authentication) to show basic OPC UA connectivity
<protocol-adapters>
    <opcua>
        <config>
            <id>opcua</id>
            <overrideUri>false</overrideUri>
            <uri>opc.tcp://opcua-server:4840</uri>
        </config>
    </opcua>
</protocol-adapters>

As a next step, you can configure to read an OPC UA nodeId from the server and publish it to an MQTT topic.

OPC UA to MQTT: Northbound

This section shows you how to define an OPC UA to MQTT configuration. The OPC UA to MQTT direction is also called northbound.

HiveMQ Edge 2024.8 introduced the concept of tags. Tags are used to simplify the usage of data from any protocol adapter. For more information, see Tags.
Example full OPC UA adapter configuration
<hivemq>
...
   <protocol-adapters>
        <protocol-adapter>
            <adapterId>simulation-server-2</adapterId>
            <protocolId>opcua</protocolId>
            <config>
                <uri>opc.tcp://CSM1.local:53530/OPCUA/SimulationServer</uri>
                <opcuaToMqtt>
                </opcuaToMqtt>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <tagName>temperature/for/machine_1</tagName>
                    <topic>machine/1/temperature</topic>
                </northboundMapping>
            </northboundMappings>
            <southboundMappings/>
            <tags>
                <tag>
                    <name>temperature/for/machine_1</name>
                    <description>This tag is about sensor data</description>
                    <definition>
                        <node>ns=1;i=1004</node>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
...
</hivemq>

The configuration example defines a connection to an OPC UA server and a northbound mapping.
The northboundMappings section defines to read data from the temperature/for/machine_1 tag that is connected to the nodeId ns=1;i=1004. The tag is published as an MQTT message to the machine/1/temperature topic . The tag is defined in the <tags> section.

Example simple MQTT message payload from a northbound connection (OPC UA to MQTT)
{
  "value": 1000
}

The OPC UA adapter publishes data values received from the OPC UA server. Depending on the data type and server configuration, the payload may include additional metadata such as timestamps and status information.

Example MQTT message payload with full OPC UA metadata
{
  "value": 23.5,
  "sourceTimestamp": "2024-01-15T10:30:00.000Z",
  "serverTimestamp": "2024-01-15T10:30:00.001Z",
  "statusCode": 0
}

The payload fields are:

  • value: The actual data value from the OPC UA node.

  • sourceTimestamp: The timestamp when the value was generated at the source (ISO 8601 format).

  • serverTimestamp: The timestamp when the OPC UA server processed the value (ISO 8601 format).

  • statusCode: The OPC UA status code indicating the quality of the data (0 indicates good quality).

Currently, the HiveMQ Edge OPC UA adapter supports subscriptions to individual OPC UA nodeIds. The publishingInterval and serverQueueSize settings apply globally to all tags in the adapter. Per-tag configuration of these values is not currently supported.

MQTT to OPC UA: Southbound

HiveMQ Edge can write to OPC UA nodes from any MQTT data sources. The southbound direction allows you to control OPC UA-connected devices by publishing MQTT messages that are converted to OPC UA write operations.

Mapping an MQTT topic filter to OPC UA data points works like the northbound mapping. The southbound mapping consists of a topic filter that includes a data schema of the MQTT payload and a tag to be written. An example configuration is shown below:

Example OPC UA southbound mapping
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>simulation-server-2</adapterId>
            <protocolId>opcua</protocolId>
            <config>
                <uri>opc.tcp://CSM1.local:53530/OPCUA/SimulationServer</uri>
                <overrideUri>true</overrideUri>
                <auth>
                    <basic>
                        <username>edge</username>
                        <password>password</password>
                    </basic>
                    <x509>
                        <enabled>true</enabled>
                    </x509>
                </auth>
                <tls>
                    <enabled>true</enabled>
                    <keystore>
                        <path>path/to/keystore</path>
                        <password>keystore-password</password>
                        <privateKeyPassword>private-key-password</privateKeyPassword>
                    </keystore>
                    <truststore>
                        <path>path/to/truststore</path>
                        <password>truststore-password</password>
                    </truststore>
                </tls>
                <security>
                    <policy>BASIC128RSA15</policy>
                </security>
                <opcuaToMqtt>
                    <publishingInterval>12</publishingInterval>
                    <serverQueueSize>13</serverQueueSize>
                </opcuaToMqtt>
            </config>
            <northboundMappings/>
            <southboundMappings>
                <southboundMapping>
                    <tagName>ns=1;i=1004</tagName>
                    <topicFilter>data/area1/#</topicFilter>
                    <fromNorthSchema>{}</fromNorthSchema>
                </southboundMapping>
                <southboundMapping>
                    <tagName>ns=2;i=1004</tagName>
                    <topicFilter>data/area2/#</topicFilter>
                    <fromNorthSchema>{}</fromNorthSchema>
                </southboundMapping>
            </southboundMappings>
            <tags>
                <tag>
                    <name>ns=1;i=1004</name>
                    <description>description1</description>
                    <definition>
                        <node>ns=1;i=1004</node>
                    </definition>
                </tag>
                <tag>
                    <name>ns=2;i=1004</name>
                    <description>description2</description>
                    <definition>
                        <node>ns=2;i=1004</node>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

OPC UA Adapter Properties

Table 10. OPC UA Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

uri

URI of the OPC UA server to connect to

URI (e.g., opc.tcp://server:4840)

overrideUri

false

Override the endpoint URI returned from the OPC UA server with the hostname and port from the specified URI

Boolean

applicationUri

Derived from certificate

Overrides the ApplicationUri used for OPC UA client identification. If not specified, uses the URI from the certificate SAN extension, or falls back to 'urn:hivemq:edge:client'

String

auth

Authentication configuration for connecting to the OPC UA server

Auth object OPC UA Authentication

tls

TLS configuration for secure connections

TLS object Properties to configure TLS

security > policy

NONE

OPC UA Security Policy to use

NONE, BASIC128RSA15, BASIC256, BASIC256SHA256, AES128_SHA256_RSAOAEP, AES256_SHA256_RSAPSS

security > messageSecurityMode

IGNORED

Message security mode. The default IGNORED lets the adapter pick a sensible value based on the configured policy: NONE for policy NONE, otherwise SIGN_AND_ENCRYPT. Set explicitly to disambiguate when an OPC UA server exposes multiple endpoints under the same security policy.

IGNORED, NONE, SIGN, SIGN_AND_ENCRYPT

opcuaToMqtt

Configuration for OPC UA to MQTT (Northbound) data flow

OpcUaToMqtt object OPC UA Northbound config details

connectionOptions

Connection handling options for heartbeats and reconnects

ConnectionOptions object OPC UA Connection Options

OPC UA Northbound config details

Table 11. OPC UA to MQTT (Northbound) (opcuaToMqtt)
Property Name Default Mandatory Description Format

publishingInterval

1000

The interval in milliseconds at which the OPC UA server sends data notifications to HiveMQ Edge. Lower values result in more frequent updates but increase network and server load.

Integer > 0

serverQueueSize

1

The number of data change notifications that the OPC UA server queues for each monitored item. Applies to VALUE tags. Higher values can prevent data loss during network interruptions but increase memory usage on the server.

Integer > 0

eventQueueSize

64

The number of event notifications that the OPC UA server queues for each event monitored item, which means CONDITION, EVENT_SUBSCRIPTION and REFRESH tags. It is separate from serverQueueSize because the same number means something different for events. A queue size of 1 asks the server for the smallest event queue it supports, not for a single entry. An event is a transition report and is never re-sent, so an entry dropped from this queue is lost for good. See OPC UA Alarms and Conditions.

Integer > 0

These settings apply globally to all tags configured for this adapter instance. Per-tag configuration of publishingInterval, serverQueueSize and eventQueueSize is not currently supported.

OPC UA Connection Options

Table 12. Connection Options (connectionOptions)
Property Name Default Mandatory Description Format

sessionTimeoutMs

120000

OPC UA session timeout in milliseconds. Session will be renewed at this interval

Integer (10000-3600000)

requestTimeoutMs

30000

Timeout for OPC UA requests in milliseconds

Integer (5000-300000)

keepAliveIntervalMs

10000

Interval between OPC UA keep-alive pings in milliseconds

Integer (1000-60000)

keepAliveFailuresAllowed

3

Number of consecutive keep-alive failures before connection is considered dead

Integer (1-10)

connectionTimeoutMs

30000

Timeout for establishing connection to OPC UA server in milliseconds

Integer (2000-300000)

healthCheckIntervalMs

30000

Interval between connection health checks in milliseconds

Integer (10000-300000)

retryIntervalMs

"1000,2000,4000,8000,16000,32000,64000,128000,256000,300000"

A comma-separated list of backoff intervals (in milliseconds) used for connection retry attempts. The adapter applies these intervals sequentially for each retry attempt. If the number of attempts exceeds the number of configured intervals, the last interval in the list is reused for all subsequent attempts. Each interval is subject to a jitter of up to +10% to reduce the likelihood of synchronized retries (which can cause device flooding).

String (for example, "1000,2000,5000"}

autoReconnect

true

Enable automatic reconnection when health check detects connection issues

Boolean

reconnectOnServiceFault

true

Enable automatic reconnection when critical OPC UA service faults occur (e.g., session invalid, subscription lost). Recommended to keep enabled

Boolean

Tag Definitions for OPC UA

The general structure of tags is defined identically for each protocol adapter. The precise details of the definition vary per protocol adapter. In OPC UA, nodeIds are configured to address specific data points.

Example tag definition
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>...</adapterId>
            <protocolId>opcua</protocolId>
            <config>
              ...
            </config>
            <tags>
                <tag>
                    <name>boiler/temperature</name>
                    <description>Provides the temperature inside the boiler</description>
                    <definition>
                        <node>ns=1;s=Temperature</node>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

The definition field is specific to OPC UA and contains the nodeId definition. Tags are defined over a list of tag-items.

Table 13. Tag definition for OPC UA NodeIds
Property Name Default Mandatory Description Format

definition > node

The OPC UA nodeId that identifies the data point on the server. For a CONDITION tag this is the alarm itself. For an EVENT_SUBSCRIPTION tag it is the notifier to subscribe to. A REFRESH tag must still carry the field, but its value is ignored, because a refresh tag always attaches to the server’s root notifier

OPC UA nodeId addressing schema

definition > kind

VALUE

What the tag follows: an ordinary variable, one alarm, a query against a notifier, or the adapter’s refresh channel. See OPC UA Alarms and Conditions

VALUE, CONDITION, EVENT_SUBSCRIPTION or REFRESH

definition > type

AlarmConditionType

For a CONDITION or EVENT_SUBSCRIPTION tag, the condition type whose fields the published message carries. Accepted and ignored for VALUE and REFRESH tags

The browse name of one of the 22 standard condition types, for example ExclusiveLevelAlarmType

definition > notifierNode

discovered

For a CONDITION tag, the node to subscribe to for the alarm’s events. Leave it empty to have HiveMQ Edge find the notifier by walking the address space; set it when the server does not publish the references that walk needs

OPC UA nodeId addressing schema

definition > sourceNode

all sources

For an EVENT_SUBSCRIPTION tag, deliver only events about this source. The source is the process object a condition watches, such as a sensor. It must be the tag’s node or a node beneath it in the event-notifier hierarchy

OPC UA nodeId addressing schema

definition > conditionNode

all conditions

For an EVENT_SUBSCRIPTION tag, deliver only events from this one condition. It must be the tag’s node or a node beneath it in the event-notifier hierarchy

OPC UA nodeId addressing schema

definition > filterType

all types

For an EVENT_SUBSCRIPTION tag, deliver only events of this type or a subtype of it. Independent of type, which decides the published shape

The browse name of one of the 22 standard condition types, for example ExclusiveLevelAlarmType

node is the only field an ordinary tag needs. A tag that leaves kind unset is a VALUE tag and behaves exactly as it did in earlier versions.

Each remaining field is read by some kinds and ignored by the others: type by CONDITION and EVENT_SUBSCRIPTION, notifierNode by CONDITION, and sourceNode, conditionNode and filterType by EVENT_SUBSCRIPTION. A field set on a kind that does not read it is accepted and has no effect.

An empty or whitespace-only kind, type or filterType counts as unset, not as a mistake. Such a field falls back to the default listed above. A value that is present but unrecognised is a configuration error.

type and filterType take the browse name of a condition type, such as ExclusiveLevelAlarmType, not a nodeId. A nodeId such as ns=0;i=9482 is rejected when the configuration is read, with an error naming the unknown type and listing the accepted ones. A browse name is a case-sensitive OPC UA identifier and is matched exactly, so exclusiveLevelAlarmType is rejected as well. Surrounding whitespace is trimmed.

OPC UA NodeId Format

The OPC UA nodeId uses a specific addressing schema that consists of a namespace index and an identifier. The general format is:

ns=<namespace-index>;<identifier-type>=<identifier>

Where:

  • ns=<namespace-index> specifies the namespace (e.g., ns=1, ns=2)

  • <identifier-type> is one of:

    • i for numeric identifiers (e.g., ns=1;i=1004)

    • s for string identifiers (e.g., ns=1;s=Temperature)

    • g for GUID identifiers (e.g., ns=1;g=550e8400-e29b-41d4-a716-446655440000)

    • b for opaque (ByteString) identifiers

Examples of OPC UA nodeId formats
ns=1;i=1004           # Numeric identifier in namespace 1
ns=2;s=Temperature    # String identifier in namespace 2
ns=3;s=85/0:Sensor1   # String identifier with path-like structure
You can discover available nodeIds on your OPC UA server using an OPC UA browser tool.

OPC UA Alarms and Conditions

From version 2026.13, the OPC UA adapter can follow a server’s alarms and conditions as well as its data variables. Alarm transitions are published to MQTT. A write back to the tag invokes the corresponding OPC UA condition method, so an operator can acknowledge an alarm from MQTT.

A tag’s kind selects what it follows:

Table 14. OPC UA tag kinds
kind Purpose Northbound Southbound

VALUE

An ordinary variable (the default)

The value

The value

CONDITION

One alarm

Transition reports for that alarm

Condition command

EVENT_SUBSCRIPTION

A query against a notifier

Transition reports from many alarms

Not writable

REFRESH

Trigger and observe condition refreshes

Refresh control events

Refresh command

METHOD

Call the methods of one object (from 2026.15)

Method responses

Method requests

Every kind but EVENT_SUBSCRIPTION can be written to. A query against a notifier has no single target, so its southbound schema deliberately accepts nothing. Writing to any tag needs a southbound mapping, which is a commercial feature. Everything northbound works without one, except a METHOD tag, whose responses answer requests that arrive through a southbound mapping. See OPC UA Method Calls.

Following one alarm

A condition tag names the alarm’s nodeId and the condition type whose fields the published message should carry:

<tag>
    <name>boiler-high-temp</name>
    <description>Boiler 1 high temperature alarm</description>
    <definition>
        <node>ns=2;s=Boiler1.HighTemp</node>
        <kind>CONDITION</kind>
        <type>ExclusiveLevelAlarmType</type>
    </definition>
</tag>

Map it northbound as you would any tag. One MQTT message is published on every transition of that alarm. The alarm activates, someone acknowledges it, and it clears. Each of those transitions is reported in its own message, which carries a snapshot of the resulting state.

A transition published by a condition tag, abridged. The full message carries every field of the declared type
{
  "value": {
    "EventId": "s1TK8F/dvUyY+EVwoH8c/ZM6AAAAAAAA",
    "EventType": { "idType": 0, "id": 9482, "namespaceIndex": 0 },
    "SourceNode": { "idType": 1, "id": "MyLevel", "namespaceIndex": 6 },
    "SourceName": "MyLevel",
    "Time": "2026-08-17T19:38:14.140Z",
    "ReceiveTime": "2026-08-17T19:38:14.140Z",
    "LocalTime": null,
    "Message": { "text": "Level exceeded" },
    "Severity": 700,
    "ConditionId": { "idType": 1, "id": "MyLevel.Alarm", "namespaceIndex": 6 },
    "Comment": { "locale": "en", "text": "night shift check" },
    "EnabledState": { "text": "Enabled", "id": true },
    "Quality": { "code": 0, "symbol": "Good" },
    "Retain": true,
    "AckedState": { "text": "Acknowledged", "id": true },
    "ActiveState": { "text": "Active", "id": true },
    "HighLimit": 70.0,
    "HighHighLimit": 90.0
  },
  "timestamp": 1786995494140
}

Reading it:

  • The whole event sits under value, wrapped by the usual northbound envelope. That is the same value/timestamp (and tagName, when the mapping asks for it) as any other tag.

  • EventId identifies the transition, not the alarm. The server mints a fresh one for each, and it is the value to echo back when acknowledging.

  • A nodeId is published as an object, {"idType", "id", "namespaceIndex"}. It is not published as the ns=6;s=…​ string used in configuration.

  • A two-state field is an object carrying the server’s display text and the machine-readable id. Decide from id: text is localized.

  • A localized text such as Message or Comment is {"locale", "text"}, with locale absent when the server did not set one.

  • A field the server has no value for is null, and the key is still there.

The published shape is decided by the type you declare, not by the device. The field sets are fixed by the OPC UA specification, and HiveMQ Edge carries all 22 standard condition types. A server that does not implement an optional member publishes it as null rather than omitting it, so a consumer can rely on the shape being stable across servers.

What is checked against the device is that the node really is the type you declared, or a subtype of it. Declaring a supertype is legitimate: an AlarmConditionType tag against a device offering ExclusiveLevelAlarmType publishes the narrower view of a richer alarm.

A field can arrive with a status code instead of a value. OPC UA allows this for a field that exists but is momentarily unavailable. Such a field is published as null and named in an unavailableFields object alongside the fields, with the server’s reason:

{ "unavailableFields": { "Comment": "Bad_UserAccessDenied" }, "EventId": "...", "Comment": null }

That key is absent when nothing was withheld.

You do not normally need to say where to subscribe. A condition is not itself an event notifier, so HiveMQ Edge finds a notifier above it by walking the server’s address space. If the server does not publish the references that walk needs, the tag is not subscribed and the reason names notifierNode as the fix.

When a tag or the adapter does not start

Three things can be wrong, and each fails at a different place. In none of them does HiveMQ Edge itself fail to start.

Table 15. Failure modes
What is wrong What happens Example message

kind, type or filterType carries a value that is not recognised

The adapter’s configuration cannot be read, so that adapter is not created. Every other adapter starts as usual, and the adapter appears once the configuration is corrected and reloaded

Unknown OPC UA condition type 'ns=0;i=9482'. Known types: ConditionType, AcknowledgeableConditionType, …

The adapter has more than one REFRESH tag

The adapter is created but fails to start, before any connection is opened

An OPC UA adapter may have at most one REFRESH tag, but 'melocoton' has 2: alarm-refresh, alarm-refresh-2.

The device disagrees with the tag

That one tag is dropped and the adapter starts with the rest. A WARN adapter event names the tag and the reason

Adapter 'melocoton' did not subscribe tag 'boiler-high-temp': tag 'boiler-high-temp' is declared as 'DialogConditionType' but the device offers 'ExclusiveLevelAlarmType', which does not derive from it

The first two are decided by reading the configuration alone, so no device is consulted and connecting could not produce a different answer. The third covers everything the server gets a say in. The node is not a condition of the declared type, no notifier can be reached, a narrowing node lies outside the notifier’s hierarchy, or the server does not answer in time. It is evaluated when the subscription is created, so it is evaluated again after a reconnect.

A dropped tag is visible without reading the log. It appears in the adapter’s event list, which the REST API serves at GET /api/v1/management/events.

A server is allowed to keep condition instances out of its address space and deliver them through events alone (OPC 10000-9 §4.3). Such a server answers a browse of the condition with Bad_NodeIdUnknown, so the declared type cannot be checked at all. HiveMQ Edge subscribes anyway and logs a warning saying the tag was subscribed without complete verification. A typo in node produces the same symptom, so read the warning rather than ignoring it.

The same applies to a sourceNode or conditionNode the server does not expose. Absence is not a negative answer, so the tag stays subscribed and the warning names the tag, the field and the node id. A narrowing node that the server does expose but that lies outside the notifier’s hierarchy is a negative answer, and that tag is dropped.

An unverified tag is an adapter event as well as a log line, so it appears in GET /api/v1/management/events beside the dropped ones.

Following many alarms at once

An event subscription tag subscribes to a notifier and reports transitions from every condition beneath it. Three optional filters narrow what gets through: sourceNode, conditionNode and filterType. They are combined, so a tag that sets none of them publishes everything the notifier carries:

<tag>
    <name>plant-alarms</name>
    <description>Level alarms under the plant notifier</description>
    <definition>
        <node>ns=2;s=Plant</node>
        <kind>EVENT_SUBSCRIPTION</kind>
        <type>AlarmConditionType</type>
        <filterType>ExclusiveLevelAlarmType</filterType>
    </definition>
</tag>
filterType and type are independent. filterType decides what gets through; type decides what shape it is published in. Filtering narrowly while publishing a broad shape is safe; filtering broadly while publishing a narrow shape is allowed and yields null fields. Both take a browse name, never a nodeId.
The 22 standard condition types

type and filterType accept the browse name of any of these:

ConditionType

DialogConditionType

AcknowledgeableConditionType

AlarmConditionType

DiscreteAlarmType

OffNormalAlarmType

SystemOffNormalAlarmType

CertificateExpirationAlarmType

TrustListOutOfDateAlarmType

TripAlarmType

InstrumentDiagnosticAlarmType

SystemDiagnosticAlarmType

DiscrepancyAlarmType

LimitAlarmType

ExclusiveLimitAlarmType

ExclusiveLevelAlarmType

ExclusiveDeviationAlarmType

ExclusiveRateOfChangeAlarmType

NonExclusiveLimitAlarmType

NonExclusiveLevelAlarmType

NonExclusiveDeviationAlarmType

NonExclusiveRateOfChangeAlarmType

The hierarchy is additive: each type carries every field its parent does, plus its own.

Acknowledging an alarm

Writing a JSON command to a condition tag through a southbound mapping invokes the corresponding OPC UA condition method. A condition tag is the clearest case of a tag whose write shape is unrelated to its read shape. A read is an alarm transition and a write is a command, so the tag publishes its own southbound schema. See Northbound and southbound tag schemas.

method is always required and is always a string. Matching is case-insensitive, and there is no numeric form. Which of the four optional fields applies follows from the method:

{ "method": "ACKNOWLEDGE", "eventId": "s1TK8F/dvUyY+EVwoH8c/ZM6AAAAAAAA", "comment": "night shift check" }

That object is the tag’s value. The condition tag’s southbound schema is {"value": <command>} with value required, so a southbound mapping has to place the command there. The field mapping’s destinations are $.value.method, $.value.eventId and so on. A message that arrives at the device without it is rejected by the write path’s schema validation with Payload serialization failed: {$: required property 'value' not found}, and never reaches the server.

A southbound mapping that turns a flat MQTT command into a condition write
<southboundMappings>
    <southboundMapping>
        <tagName>boiler-high-temp</tagName>
        <topicFilter>cmd/boiler/high-temp</topicFilter>
        <fromNorthSchema>{}</fromNorthSchema>
        <fieldMapping>
            <instructions>
                <instruction><source>$.method</source><destination>$.value.method</destination></instruction>
                <instruction><source>$.eventId</source><destination>$.value.eventId</destination></instruction>
                <instruction><source>$.comment</source><destination>$.value.comment</destination></instruction>
            </instructions>
        </fieldMapping>
    </southboundMapping>
</southboundMappings>

With that mapping in place, publishing the command above to cmd/boiler/high-temp acknowledges the transition, and the server answers with a fresh transition on the tag’s northbound topic carrying "AckedState": {"text": "Acknowledged", "id": true} and the comment.

Table 16. Condition methods
Method Required arguments comment Acts on

ACKNOWLEDGE

eventId

Yes

One transition

CONFIRM

eventId

Yes

One transition

ADD_COMMENT

eventId

Yes

One transition

RESPOND

selectedResponse

Yes

A dialog condition

TIMED_SHELVE

duration

Yes

Shelving state

ENABLE

none

No

The condition

DISABLE

none

No

The condition

SILENCE

none

No

The condition

SUPPRESS

none

Yes

The condition

UNSUPPRESS

none

Yes

The condition

REMOVE_FROM_SERVICE

none

Yes

The condition

PLACE_IN_SERVICE

none

Yes

The condition

RESET

none

Yes

The condition

UNSHELVE

none

Yes

Shelving state

ONE_SHOT_SHELVE

none

Yes

Shelving state

comment is optional everywhere it is accepted. Where the method has no comment argument of its own, HiveMQ Edge calls the specification’s 2 variant (Suppress2, Reset2, and so on) when the server offers it. ENABLE, DISABLE and SILENCE have no such variant in any version of the specification, so a comment sent with them cannot reach any server; HiveMQ Edge logs a warning and makes the call without it.

One worked example per argument shape:

{"method": "ACKNOWLEDGE", "eventId": "s1TK8F/dvUyY+EVwoH8c/ZM6AAAAAAAA", "comment": "checked"}
{"method": "TIMED_SHELVE", "duration": 60000}
{"method": "RESPOND", "selectedResponse": 1}
{"method": "ENABLE"}
Table 17. Command fields
Field Type Meaning

method

String

Which method to invoke, named as in the table above. Always required, matched case-insensitively

eventId

String

The EventId of the transition being responded to, base64 exactly as it was published. Required for ACKNOWLEDGE, CONFIRM and ADD_COMMENT

comment

String

Free text the server records alongside the transition

duration

Number

Shelving time in milliseconds. Required for TIMED_SHELVE

selectedResponse

Integer

Zero-based index into the dialog’s ResponseOptionSet, an OPC UA Int32 (0 to 2147483647). Required for RESPOND

comment distinguishes absent from empty, because OPC UA does. Omitting the field leaves any existing comment unchanged. Sending "comment": "" erases it. A comment change raises a fresh event, so every other client watching that alarm is told the note is gone. A comment that is not a string is rejected rather than coerced.

Do not send method, eventId, duration, or selectedResponse as an explicit null. None of these four fields admits null in the southbound schema, so a command that carries one is refused by the write path’s schema validation and never reaches the server. To say nothing about a field, leave the key out. The comment field is the exception: "comment": null is accepted and means the same as omitting the key.

This matters for a caller that builds the command as an object and then serializes it. Jackson, JSON.stringify and json.dumps all write "field": null for a member that was never assigned, so such a caller sends nulls it never meant to send. Suppress the null keys instead, with @JsonInclude(NON_NULL), a JSON.stringify replacer, or model_dump(exclude_none=True).

An eventId supplied to a method that does not take one is ignored rather than rejected. An eventId that is not valid base64 is rejected, as is a selectedResponse outside the Int32 range.

Refreshes, and recovering the current picture

A transition is a report of a change, so a consumer that connects later has not seen the alarms that were already active. OPC UA answers this with ConditionRefresh, which makes the server re-report its retained conditions as though each had just transitioned.

HiveMQ Edge issues one automatically whenever the adapter carries any event tag. It does so on connect, on every reconnect, and whenever the server reports that a refresh is required. No configuration is needed for that. A REFRESH tag adds two things: it publishes the refresh control events, and it lets you trigger a refresh by hand with a southbound write.

<tag>
    <name>alarm-refresh</name>
    <description>Refresh channel for this adapter</description>
    <definition>
        <node>ns=0;i=2253</node>
        <kind>REFRESH</kind>
    </definition>
</tag>

The node is required by the configuration format but ignored: a refresh tag always attaches to the server object. The southbound command has one defined method. Like a condition command, it is the tag’s value, so a southbound mapping maps it to $.value.method:

{ "method": "REFRESH" }

Anything else is rejected: writing ACKNOWLEDGE to a refresh tag means two tags have been confused, and silently refreshing instead would be a worse answer than an error.

A refresh tag publishes the control events that reach a monitored item whatever its filter says, and which are dropped on every other kind of tag:

Table 18. Control events published by a refresh tag
Event What it means

RefreshStartEventType

The server has begun re-reporting its retained conditions

RefreshEndEventType

It has finished. Everything between the two is the current picture, not new transitions

RefreshRequiredEventType

The server can no longer guarantee you are in sync and is asking for a refresh. HiveMQ Edge requests one automatically; the event tells you it happened

EventQueueOverflowEventType

This tag’s own event queue overflowed and older notifications were discarded. Delivered only to the item that overflowed, so it appears here only when the refresh tag itself lost notifications

Control events are published in the BaseEventType shape and in no other. That shape is EventId, EventType, SourceNode, SourceName, Time, ReceiveTime, LocalTime, Message and Severity. A refresh tag has no alarm state, so type is ignored on it and none of the condition fields appear.

The bracket around one refresh, as published
{"value": {"EventId": "8nA+GRRuwUO6/7xL3BH0Ig==",
           "EventType": {"idType": 0, "id": 2787, "namespaceIndex": 0},
           "SourceNode": {"idType": 0, "id": 2253, "namespaceIndex": 0},
           "SourceName": "Server", "Time": "2026-08-17T19:41:20.963Z",
           "Message": {"text": "Refresh Start"}, "Severity": 1}, "timestamp": 1786995681161}

{"value": {"EventId": "2UrJ0UPOikG68DkCeWYizg==",
           "EventType": {"idType": 0, "id": 2788, "namespaceIndex": 0},
           "SourceNode": {"idType": 0, "id": 2253, "namespaceIndex": 0},
           "SourceName": "Server", "Time": "2026-08-17T19:41:20.963Z",
           "Message": {"text": "Refresh End"}, "Severity": 1}, "timestamp": 1786995681161}

The re-reported conditions themselves arrive on the condition and event subscription tags between those two, as ordinary transitions.

At most one refresh tag per adapter. An adapter configured with two does not start, and the error names them. The refresh bracket is copied to every notifier item in a subscription, so two refresh tags would each publish the same events and look like two refreshes had happened.

A refresh tag is not a general loss monitor. When a server’s event queue for a monitored item fills and older notifications are discarded, OPC UA delivers the overflow event only to the item that overflowed. For any other tag that is reported as an adapter event naming the tag, and counted in the subscription.event.queue.overflow.count metric. It does not appear on the refresh tag’s topic.

This matters because an event is a transition report and is never re-sent. Neither a reconnect nor a ConditionRefresh can reconstruct it, so a dropped transition leaves a hole in the alarm history. If it recurs, raise eventQueueSize.

OPC UA Method Calls

Calling a method

OPC UA devices offer more than values to read and write. Many also offer methods: operations that you call with arguments and that return results, like a function call. A boiler can offer Start, Stop, and SetSetpoint. A filling machine can offer LoadRecipe. The device decides which of its functions it offers as methods, and some functions it offers only as methods.

From version 2026.15, Edge can call these methods for an MQTT client. You publish a request, an MQTT message that names the method and carries its arguments. Edge calls the method on the device and publishes the result as a response, another MQTT message. Your application never speaks OPC UA itself.

In OPC UA, a method belongs to an object: the node that represents a device or one of its parts. In Edge, you create one tag for that object, with the kind METHOD, and two mappings. The southbound mapping maps each request to a call of the method. The northbound mapping maps each result to a response. One tag serves every method of the object, because each request names the method that it calls.

Southbound mappings require HiveMQ Edge’s commercial functionality and a valid license.

Method calls require HiveMQ Edge 2026.15 and the commercial module of the same version, which ship together in one distribution.

The tag names the object:

<tag>
    <name>boiler</name>
    <description>Boiler 1, whose methods this tag calls</description>
    <definition>
        <node>nsu=http://vendor.example/Boiler;s=Boiler1</node>
        <kind>METHOD</kind>
    </definition>
</tag>

Create a southbound mapping from a request topic to the tag, and a northbound mapping from the tag to a topic for the responses. In the southbound mapping, select This mapping carries method calls.

To call the method Square with the argument input1, publish this request to the southbound mapping’s topic:

{
  "methodName": "Square",
  "value": {
    "input1": 7
  }
}

Edge calls the method and publishes this response to the northbound mapping’s topic:

{
  "responseMethodName": "Square",
  "value": {
    "output1": 49
  },
  "timestamp": 1761036902117
}

The response names the method in responseMethodName. Read it as response from methodName.

A request can also carry two optional fields. correlationData, if present, comes back on the response, so that you can match a response to the request that produced it. A reply address sends the response to a topic other than the mapping’s own topic. Each field needs its own mapping setting.

What a method call does not do

Edge calls the method and publishes what the device returns as a response. Edge does not retry, buffer, or interpret.

A method call has a side effect, so Edge does not retry a call on your behalf. If a response does not arrive, the method can still have run. Only the device’s state tells you whether it ran.

Edge guarantees nothing about requests that you publish while you change a configuration. If a request must not be lost, do not publish into a configuration change.

Setting up a method call

The tag

A method tag carries two fields in its definition:

Field Contents

node

The node id of the object whose methods you call. For the two forms that a node id takes, see Naming the namespace.

kind

METHOD

The tag editor for a method tag
Figure 1. The tag editor for a method tag, here named methods. The editor labels kind as Node kind and node as Destination Node ID.

After the adapter connects, Edge verifies three things about the tag: that the node exists, that the node is an object, and which methods the object offers. If Edge cannot verify the tag then, the first request to the tag verifies it again. A method tag that fails verification does not stop the adapter, and does not fail the adapter’s other tags.

Southbound: the mapping that receives requests
Setting config.xml element Default Select it to get

This mapping carries method calls

methodCalls

Off

Edge reads methodName and calls that method. Select this setting for any method tag. If you leave it off, Edge calls no method and refuses a request to a method tag with Bad_MethodInvalid.

Requests carry correlation data

correlationData

Off

Edge reads correlationData, from the correlationData payload field or the MQTT 5 Correlation Data property.

Requests carry a response topic

responseTopic

Off

Edge reads the reply address, from the responseTopic payload field or the MQTT 5 Response Topic property, so that a caller can choose where the response goes.

The method call settings in the southbound mapping editor
Figure 2. The Method calls settings in the southbound mapping editor, all three selected.

The first setting governs the other two. With method calls off, Edge gathers no request parameters, so the other two settings have no effect, and the mapping editor disables them. With method calls on, the other two are independent of each other. For a request whose response you do not need, select only the first setting.

In config.xml, an absent element means false.

Exactly one southbound mapping can match a tag and topic filter. If two mappings match, Edge does not choose between them and reads no method-call settings at all. Method calls through such a mapping fail as if the first setting were off.

Northbound: the mapping that publishes responses

A method tag needs a northbound mapping, which publishes the responses. No northbound setting is specific to method calls.

A northbound mapping for a method tag
Figure 3. A northbound mapping for a method tag, here methods, that publishes to the topic method-sim/response.

If a method tag has no northbound mapping, Edge still runs the calls and discards the responses.

With a reply address, Edge publishes one copy of the response per northbound mapping configured for the tag, not one copy in total.

The schema on your topic filter

A method request must carry methodName in its payload. In the schema on your topic filter, declare methodName as a required string property.

A request can carry correlationData and responseTopic in its payload or as MQTT 5 properties. In your schema, declare both as optional string properties.

If you save a mapping with This mapping carries method calls selected in the UI or through the REST API, and your schema does not require methodName, Edge writes a warning to the log, but still saves the mapping. Edge does not check a mapping that you write into config.xml. To test your schema, Edge validates an empty object against it, and warns unless the validation reports methodName as missing. The test finds a requirement in a root required array, in an allOf branch, or behind a $ref. If you state the requirement only under a condition, such as in an if/then pair, Edge warns although your schema is correct. If one branch of an anyOf requires methodName and another does not, Edge does not warn, although such a schema accepts a request without methodName.

A complete config.xml
<protocol-adapter>
    <adapterId>opcua-1</adapterId>
    <protocolId>opcua</protocolId>
    <config>
        <!-- your connection settings -->
    </config>

    <tags>
        <tag>
            <name>boiler</name>
            <description>Boiler 1, whose methods this tag calls</description>
            <definition>
                <node>nsu=http://vendor.example/Boiler;s=Boiler1</node>
                <kind>METHOD</kind>
            </definition>
        </tag>
    </tags>

    <southboundMappings>
        <southboundMapping>
            <tagName>boiler</tagName>
            <topicFilter>cmd/boiler/call</topicFilter>
            <fromNorthSchema>{}</fromNorthSchema>
            <methodCalls>true</methodCalls>
            <correlationData>true</correlationData>
            <responseTopic>true</responseTopic>
            <fieldMapping>
                <instructions>
                    <instruction><source>$.value</source><destination>$.value</destination></instruction>
                </instructions>
            </fieldMapping>
        </southboundMapping>
    </southboundMappings>

    <northboundMappings>
        <northboundMapping>
            <tagName>boiler</tagName>
            <topic>responses/boiler</topic>
            <maxQos>1</maxQos>
            <includeTagNames>false</includeTagNames>
            <includeTimestamp>true</includeTimestamp>
            <includeMetadata>false</includeMetadata>
            <mqttUserProperties/>
            <messageExpiryInterval>4294967295</messageExpiryInterval>
        </northboundMapping>
    </northboundMappings>
</protocol-adapter>

The example’s fromNorthSchema is the schema on your topic filter. {} checks nothing, so it does not require methodName, as The schema on your topic filter above advises. Replace it with your own schema.

The southbound mapping needs the fieldMapping instruction shown above. The mapping’s field mapping is a whitelist: the field mapping rebuilds the payload from an empty object, and drops every field that no instruction names. A mapping with no instructions therefore drops every field of every request. The arguments of your request sit inside value, and the generated schema requires value. If the field mapping drops value, Edge republishes the request on $invalid/, and the request never reaches the device:

Payload serialization failed: {$: required property 'value' not found}

The quarantine needs the tag’s generated schema. If Edge could not resolve that schema (see On a device slow to connect, the schema check might be absent), nothing checks for value, and Edge does not republish the request on $invalid/. Edge then calls the method with no arguments: a method that takes none runs, and a method that takes some is answered with Bad_ArgumentsMissing.

A method request’s other fields (methodName, correlationData, and responseTopic) need no instruction. Edge reads those before the field mapping runs and hands them to the adapter separately.

The mapping editor lists methodName among the required properties to set, because a request must carry it. Leave it unmapped: Edge takes it from the request as it arrives.

This applies to every southbound mapping of every tag kind, not only to method calls.

What makes a message a method call

Three conditions together make a southbound message a method call:

  • The payload carries a non-blank methodName.

  • The southbound mapping for that tag and topic filter has This mapping carries method calls selected.

  • The tag’s kind is METHOD.

Edge consults nothing else. A message that fails any one of the three conditions is not a method call.

A response fails the first condition, because a response names the method in responseMethodName. If a response arrives where Edge reads requests, Edge quarantines the response because it names no method. The response calls nothing.

The distinction matters because a reply address can name any topic that Edge can publish to, and a northbound mapping’s topic is equally free. If a method tag’s responses go to the topic where the tag’s own requests arrive, every response lands where Edge reads requests. Because a response cannot pass for a request, no response triggers a call.

Naming the method

The methodName field names the method to call. Edge matches the method’s browse name on the server, exactly. Case matters.

Do not confuse methodName with the method field of a condition command. A condition command carries method inside value, and Edge matches it without regard to case. A method call carries methodName at the payload root, and Edge matches it exactly.

Methods that the object inherits from its type

Edge enumerates all methods of the object that your tag names, and of that object’s type. Edge also enumerates the methods of every type up the chain that the object derives from. You can call a method by its BrowseName in two cases:

  • The name is unique in the entire set.

  • The name belongs to exactly two methods: one on the object, and one declaration on one of the types, that is, a method with a modelling rule such as Mandatory or Optional. The method on the object wins.

You can also call any of these methods by the node id of the method node. Edge matches the node id only against the methods it found this way. If a nearer type declares a method of the same name, Edge does not offer the farther type’s declaration, and its node id is not found.

To call a method, Edge reads the method signatures from the server: which methods exist, and the arguments of each. Some servers restrict access to their type nodes, so this read can fail. If the read fails:

  • The call can fail.

  • Edge may read the method signatures again, so a later call can succeed.

  • Edge shall read the method signatures again when you restart the adapter.

Edge promises nothing beyond these three points.

When two methods share a name

An object can expose two methods with the same name. OPC UA requires a browse name to be unique on a type definition, not on the instance that a method tag points at. One object can therefore carry a Start from each of two vendors' interfaces.

The value of methodName therefore takes two spellings. Edge tells the spellings apart by whether the value contains a semicolon:

Spelling Example Resolves

The plain name

Start

If exactly one method has that name, or if the only other is a declaration on one of the object’s types.

The method node

nsu=http://vendor.example/Boiler;s=Start

For every method that Edge found on the object and its types, because it names the node itself uniquely.

Use the plain name. If two methods share it, Edge refuses the request, and the log lists both node ids. Put one of them in methodName instead.

The identifier after the semicolon is whatever the server assigns: s= for a string, i= for a number, g= for a UUID in its full form 8-4-4-4-12, and b= for base64 bytes.

Use the method’s actual node id, which is what Edge matches. A node id names a node by its identifier, and the identifier need not be the same string as the browse name. If the two differ on your server, copy the node id that your browser shows for the method. Do not build a node id from the name.

Naming the namespace

Give the namespace in either of two forms, as you can for a tag’s own node id:

Form Example Use it when

URI

nsu=http://vendor.example/Boiler;s=Start

Preferred. The URI is stable across sessions.

Index

ns=2;s=Start

Suitable for a request that you send once.

Prefer the URI form. A namespace index is a position in the server’s own table, and the index is valid only for the session that reads it. A server can renumber the table. A request that you store, retain, or replay then names a different method, and nothing warns you.

methodName always needs the namespace. A tag’s node id accepts i=85 for namespace 0, but in methodName a value without a semicolon is a plain name. Write a method of namespace 0 as ns=0;i=....

When Edge refuses a request, the log lists node ids in the URI form wherever the server publishes the namespace’s URI. Two exceptions: Edge prints a node id of namespace 0 as i=... without a namespace, and a namespace without a published URI in the index form. Add ns=0; before you use a node id of namespace 0 in methodName.

A method whose name contains a semicolon

Address such a method by its full node id. The plain-name spelling does not work for such a method, because Edge reads methodName as a node id whenever the value contains a semicolon.

"methodName": "ns=1;s=Start;Stop"

Only the first semicolon separates the namespace from the identifier. Everything after the first semicolon is the identifier, so nsu=http://vendor.example/Boiler;s=Start;Stop resolves to the method whose node identifier is Start;Stop in that namespace.

The request

A request carries its fields at the root of the payload, beside value:

Field Required Contents

value

Yes

An object that holds the arguments, keyed by the names that the device declares. If the method takes no argument, send the empty object {}.

methodName

Yes

The method to call. See Naming the method.

correlationData

No

An opaque string, echoed on the response. Edge reads it only if the mapping has Requests carry correlation data selected.

responseTopic

No

The topic that the response goes to, instead of the mapping’s own topic. Edge reads it only if the mapping has Requests carry a response topic selected. The value must be a topic that Edge can publish to.

Put these three fields beside value, never inside it. A method can declare an argument of any name, those three included, without a collision. The device names what sits inside value, and Edge names what sits outside value.

correlationData and responseTopic must each be a string. Edge refuses a value of any other JSON type, and the request schema refuses a null in either field. To send no value, leave the field out. An empty or blank responseTopic means that you name no address.

MQTT 5 properties

On MQTT 5, you can send correlationData and the reply address as properties instead of payload fields:

Payload field MQTT 5 property

correlationData

Correlation Data (0x09)

responseTopic

Response Topic (0x08)

One mapping setting governs both sources. If you select Requests carry correlation data, Edge reads correlationData from whichever place carries it.

When a value arrives twice

A value present in only one place is the value Edge uses. If both the MQTT 5 property and the payload field carry a value, the two must agree. Edge uses the property’s value and refuses a request whose two sources disagree. A blank Response Topic property carries no value, so Edge then uses the payload field.

A reply address must match exactly, as text. Edge normalizes nothing. Edge does not trim the address, does not fold its case, and does not treat a trailing slash as equivalent. An MQTT topic is a byte string, and a/b is not a/b/.

correlationData must agree, and Edge compares generously. The payload field must be a string. Edge compares that string against the property’s bytes in three forms, in this order:

  1. The UTF-8 encoding of the string.

  2. The base64 decoding of the string.

  3. The base64 decoding of the string, after Edge strips a leading base64:.

Any one match is agreement. Edge itself publishes the third form. If you take correlationData from a response and send it back unchanged, it therefore agrees with the property that it came from.

A disagreement is a syntactic error. Edge republishes your request on $invalid/ followed by the topic that you published to, publishes no response, and does not call the device.

A JSON string cannot hold arbitrary bytes. If your correlationData holds arbitrary bytes, send it as the MQTT 5 property alone, and omit the payload field. The rule is that two present values must agree, never that both must be present.

The request schema

You do not write this schema. Edge generates it from the object’s methods when it verifies the tag.

The schema lists every argument of every method on the object, all optional, and gives each argument a type where it can. Some arguments stay "any value"; the subsections below name them. An argument name that no method declares therefore fails validation before Edge calls the device. The schema cannot express a set of arguments that depends on the method name, so the schema names every argument of every method, unpaired. Every type that the schema states is correct, and the adapter catches a mismatch between an argument and the method that you named.

null is a value, not a way to leave something out. An argument, or a field inside a structure argument, accepts null only where its OPC UA type has a null value: a String, a ByteString, a NodeId or a LocalizedText, for example. Edge then sends that type’s null value to the device. One exception: for a String argument or value on its own, Edge can send only an untyped null, because the OPC UA library inside Edge cannot carry a typed null String. A server that checks argument types can refuse it with Bad_TypeMismatch, as a Siemens S7-1500 does. Inside a structure or an array, a null String keeps its type. An array never accepts null: see Array arguments. Where the type has no null value, Edge refuses null. For a number, a Boolean or a DateTime, the request schema refuses it. For an enumeration or a structure, whose schema states "any value", Edge refuses it when it converts the argument, and publishes the refusal as a response. The same rule holds for an ordinary value write.

Argument types

Every method argument carries a declared type. The server publishes that type as part of the method’s signature, and Edge reads the type when Edge browses the object.

Edge converts an argument whose declared type is one of the 21 well-known builtin types that OPC UA defines. For each, send this:

The server declares Send Valid values

Boolean

A JSON boolean

true or false

SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64

A JSON number, whole

Inside the type’s range. Below 2^53 in magnitude

Float, Double

A JSON number

Inside the type’s range

String

A JSON string

Any text

DateTime

A JSON string

An ISO 8601 timestamp, such as 2026-10-19T14:30:00Z

ByteString

A JSON string

Base64

Guid

A JSON string

A UUID, such as 6d1a9e2c-4f3b-4a21-9c7e-1b2d3f4a5b6c

NodeId, QualifiedName, LocalizedText

A JSON string, or the object Edge publishes for that type

Either form. "Motor" or {"name": "Motor", "namespaceIndex": 2}

ExpandedNodeId, XmlElement

A JSON string

A node id with a namespace, or XML text

StatusCode

A JSON number, or an object with code

2155085824 or {"code": 2155085824}

Alias names. A server can define its own type as a name for one of the 21. Edge asks the server what the name stands for, and converts the argument accordingly. Duration is a name for Double, measured in milliseconds, so Edge converts a Duration argument and you send a JSON number.

Edge refuses an argument of three kinds of type. Edge does not call the device, and the log names the argument and its type.

Refused Because

Variant, DataValue and DiagnosticInfo

The declaration tells you nothing about what to send.

An abstract type, such as the base types Structure and Enumeration

JSON cannot say which concrete type you mean. A concrete structure or enumeration type works: see Structure arguments and Enumeration arguments below.

A union: a structure type, from OPC UA 1.04, in which exactly one field holds a value

Edge does not encode a union in this version.

A Float or a Double argument takes a JSON number only. If you send "NaN" for such an argument, the request fails the request schema. The response direction differs: see An output that JSON cannot express.

Structure arguments

A structure argument is a JSON object, keyed by the structure’s field names, exactly as Edge publishes a structure that it reads from a device.

{
  "methodName": "SetRecipe",
  "value": {
    "recipe": {
      "name": "Batch-7",
      "temperature": 180.5,
      "holdSeconds": 240
    }
  }
}

Use the field names that the server’s own definition gives, and match their case. An analog item’s Range has the fields Low and High.

Send every field that the definition does not mark optional. Edge refuses a structure that omits a required field, and does not choose a value for the field. The device acts on any value that Edge picks. To omit an optional field, leave it out of the object. You can omit optional fields only at the end of the structure: Edge refuses a structure that omits an optional field and gives a later one. A null does not omit a field: it is the field’s null value, as described in The request schema above.

Send no field that the definition does not declare. Edge refuses an unknown field name rather than ignore it. Edge refuses a misspelled "temprature" as an unknown field. Edge does not drop it and send the structure without the temperature that you meant to send.

The request schema describes a structure’s fields, so the shape is checked before Edge calls the device. Some fields stay as "any value" inside that description: a field whose type is an enumeration, a field of a builtin type that Edge accepts in two forms, a field of an abstract type, and a nested structure that Edge cannot resolve. Edge checks them when it converts the argument.

Edge reads a structure’s definition from the server twice. When it browses the method, it reads the definition to describe the argument in the request schema. If that read fails, the schema states "any value" for the argument, and Edge still verifies the tag. When you call the method, Edge reads the definition again to convert the argument. If that read fails, Edge refuses the argument, and the log names it.

Enumeration arguments

An enumeration argument takes three forms, and Edge accepts any of them:

Form Example Available

The integer

2

Always. It is what the wire carries.

The symbolic name

"Running"

When the server gives the enumeration a definition, which servers from OPC UA 1.04 do.

An object carrying either or both

{"value": 2}, {"name": "Running", "value": 2}

Always, when it carries value. An object carrying only name needs a definition, like the bare name.

The third form is what Edge publishes for an enumeration inside a structure. You can therefore send a structure that you read from a device back unchanged, unless the structure has a field that Edge cannot send: a field of an abstract type, such as BaseDataType or Structure, or a union field. Edge publishes a plain enumeration (a variable, or a method’s output) as the integer, and accepts the integer back.

On a server that gives the enumeration a definition, Edge refuses a number that the enumeration does not define. The log names the values that the enumeration does define. A device that receives an undefined value can act on it rather than refuse it.

Some servers give an enumeration no definition, typically servers older than OPC UA 1.04. Such a server can still list the enumeration’s names, but Edge does not use that list. Edge then accepts only a number, bare or as value, and accepts any number unchecked.

On a server that gives the enumeration a definition, Edge refuses an object whose two fields disagree. The fields disagree when the enumeration gives the name and the value to different values. Edge resolves the conflict in favor of neither. A caller who changed one field and not the other meant something, and nobody can know which field holds the intent. Send one field, or both fields in agreement. Without a definition, Edge uses value and does not check name.

The request schema states "any value" for an enumeration argument, because Edge’s schema model cannot state a set of permitted values. Edge checks the value when it converts the argument, and publishes a refusal as a response rather than as a quarantine.

Array arguments

If the method declares an argument as an array, send a JSON array. Edge refuses a bare number and does not wrap it for you.

The schema states no array length, whatever the device declares. An OPC UA array dimension is a maximum rather than an exact size, so a declaration of five elements does not mean exactly five. The two directions differ:

You send What happens

More elements than the device declares

The device can refuse the call. Edge then publishes the refusal as a response.

Fewer elements than the device declares

A legal request. Edge passes it on, and the device decides what to do about the elements that you omit.

Nothing reports an undersized call. Consider a programmable logic controller (PLC) whose method takes a fixed-size array. The missing elements usually keep the values that they held before, which can include the values from your previous call. Send the number of elements that the method expects.

A multi-dimensional array must be rectangular. Every list at the same depth must have the same length, and Edge refuses a request whose lists disagree. The log names the depth and both lengths.

Accepted:  [[1, 2], [3, 4]]      Both inner lists hold 2 elements.
Refused:   [[1, 2], [3]]         2 against 1.
Refused:   [[[1]], [[2, 3]]]     The inner lists are 1 against 2, in different branches.
Accepted:  [[], []]              A rectangular 2x0 value.

Edge compares lengths per depth, not per parent, which is why the third line is refused.

An array never accepts null, whatever its element type, and neither does a list inside a multi-dimensional array. To send an array with no elements, send []. OPC UA treats a null array and an empty array as the same value, so [] says everything that null would. A device can still refuse [] for an array of fixed length: a Siemens S7-1500 refuses it for an Int32[5] argument with Bad_InternalError, and Edge publishes the refusal as a response. The elements of an array accept null where their type has a null value: ["a", null] is a valid String array.

Arguments whose shape the device leaves open

A server states each argument’s shape as a value rank. Three of the possible ranks do not fix a shape:

The device declares You can send

An array of one or more dimensions

An array of any depth. Not a single value.

A single value or an array of any depth

Either, at any depth.

A single value or a one-dimensional array

Either. Edge refuses an array that nests deeper.

For these three ranks, the schema states only "any value", because Edge’s schema builder cannot express "a single value or an array". Edge therefore takes the shape from what you send. If the shape does not match the method’s real signature, the device can refuse the call. Edge then publishes the refusal as a response.

Most arguments do not fall here. A concrete method usually declares a concrete shape, and the schema then describes and checks it.

Whole numbers of magnitude 2^53 or more

Edge refuses a request that carries a whole number whose magnitude reaches 2^53, which is 9007199254740992, for an argument of an integer type. The largest whole number that you can send is 9007199254740991. Only the two 64-bit integer types, Int64 and UInt64, have a range that reaches this limit.

Every southbound write, whether a method call or an ordinary value write, passes through the southbound mapping’s field schema validation and transformation. Edge runs this step as JavaScript, and JavaScript holds every number as an IEEE 754 double. As a consequence, an adapter cannot always tell whether a number that it receives is exactly the number in the original MQTT message. For example, if the adapter receives 9007199254740992, the original message contained either 9007199254740992 or 9007199254740993. The OPC UA southbound path is conservative and rejects every whole number that can be the result of rounding: every number greater than or equal to 253, or less than or equal to -253. The rule applies to a method argument and to an ordinary value write alike. The rule does not affect floating-point numbers. Other adapters can be more lenient.

The response

A response carries its fields at the root of the payload, beside value, exactly as a request does:

Field Present Contents

value

Always

The output arguments by name on success, or the empty object {} if the method returns none. JSON null on failure. An individual output is null when the device returns no value for it, or when Edge cannot decode it.

responseMethodName

Always

The method that the request named. The field is present and empty on the two refusals where no method name reaches Edge.

errorCode

On failure

The OPC UA status code by name, for example Bad_NotExecutable.

statusInfo

When there is detail to report

See Status detail.

correlationData

When the request carries correlationData and the mapping reads it

The request’s correlationData.

tagName

If the mapping includes it

The method tag’s name.

timestamp

If the mapping includes it

When Edge produces the response.

metadata

If the mapping includes it

Always null for a method response.

mqttUserProperties

If the mapping defines user properties

The mapping’s user properties.

No northbound setting governs any of this. A response carries what the request carries: correlationData if you send it and the mapping reads it, and an errorCode if the call fails. The response goes to the address that the request names, or to the mapping’s own topic.

Testing whether a call succeeded

Test for errorCode, and for nothing else. If errorCode is present, the call failed. If errorCode is absent, the call succeeded. No success flag exists, and no other field answers the question:

  • Not value. A failed call publishes value as null, and a successful call that returns no output publishes {}. Test errorCode all the same: it is the field that states the result. A null inside value, under an output’s own name, means something narrower: the device returned no value for that one output, or Edge cannot decode it. In the second case, statusInfo.undecodedOutputs names the output and carries its body.

  • Not statusInfo. The field carries detail about the response, which a successful call can also have. statusInfo names an output that Edge cannot decode, whether the call succeeded or failed.

Edge also sets errorCode for an Uncertain_ status. The device responded, and the method possibly ran. A caller that retries on any errorCode can therefore run a method twice. Check the device’s state before you repeat a call that reports an Uncertain_ status.

correlationData in a response

Edge writes correlationData to both the payload field and the MQTT 5 Correlation Data property, on every response to a request that carries it.

You send correlationData as The payload field reads The MQTT 5 property carries

A correlationData payload field

Your text, unchanged

Your text as UTF-8

An MQTT 5 Correlation Data property

base64: followed by the base64 form

Those exact bytes

If you send both, the property and an agreeing payload field, the response carries the property’s form: the payload field reads base64: followed by the base64 form, not your text.

If you send correlationData as text alone, it comes back verbatim, so you can match it as it stands. If you send it as the MQTT 5 property, the payload field holds it with a prefix. To recover the bytes, strip base64: and decode the rest. An empty correlationData survives the round trip and travels as base64: with nothing after it.

Two facts force this encoding. The Correlation Data property holds binary data, and a JSON string holds text, so the payload cannot carry arbitrary bytes unaltered. Also, the audience of a response is not necessarily the caller, because a request can name any reply address. The subscriber that reads the response can be an MQTT 3 client with no property to read. For such a client, the payload is the only field that it sees.

Status detail

When statusInfo is present, it holds up to three parts, each only when there is something to report:

Part Appears Contents

deviceOutput

On a failure that the device explains

The values that the method returns to explain itself

arguments

On a failure for which the server reports a status per argument

Every named argument the server reported on, with its status, Good ones included. The server reports an argument by position, and Edge translates the position back to a name.

undecodedOutputs

On any call with an output that Edge cannot decode

Keyed by the output’s name, with reason, typeId, encoding, and body

If there is nothing to report, statusInfo is absent. The presence of statusInfo does not signal a failure, because the third part appears on calls that succeed.

An output that Edge cannot decode

Edge publishes an output that it cannot decode as null. To read a structure that a method returns, Edge needs the field description for that structure. Edge reads the description from the server. Without that description, Edge publishes that output as null and publishes the rest of the response unchanged. Under the output’s name, the entry in undecodedOutputs carries three things:

  • Why Edge cannot read the output.

  • The type that the server named.

  • The body as the device sent it: base64 for a binary body, and the text itself for an XML or a JSON body. Decode that body yourself.

An output that Edge cannot decode does not make a call fail. A call that succeeded keeps value and sets no errorCode. A call that the device reported as failed keeps its errorCode. A failed call’s deviceOutput goes through the same decoding. An output listed in undecodedOutputs can therefore be the device’s explanation of why it refused, rather than a method’s result. Edge logs a warning. Edge may read the type description again, for example after the session to the device is re-established, so a later call can decode the output.

A structure that OPC UA itself defines, such as Range or EUInformation, is different. Milo, the OPC UA library inside Edge, decodes it without the server’s description. Edge needs a description only to publish the structure as an object, and takes it from Milo when the server gives none. If Edge cannot use either, for example because it cannot read the server’s type hierarchy, it publishes the output as text: the library’s own rendering, such as Range{low=1.5, high=9.0}. Edge logs a warning, and statusInfo says nothing about it. Such an output arrives as a string where the response schema states an object.

An output that JSON cannot express

If a Float or a Double output holds a value that JSON cannot express, Edge publishes the output as a string: "NaN", "Infinity", or "-Infinity". The schema states number for such an output, because JSON has no number for these values.

The response schema

You do not write this schema either. Edge generates the response schema from the object’s methods. The response schema describes the output arguments in the same way that the request schema describes the input arguments.

The schema declares every output nullable, whatever its type, because any output can arrive as null when Edge cannot decode it.

Edge does not validate a response before Edge publishes it. You can validate a response yourself against the response schema.

When a request fails

The syntactic checks

Edge checks every request before it calls the method. It checks correlationData only if the mapping has Requests carry correlation data selected, and the reply address only if the mapping has Requests carry a response topic selected. These are the syntactic checks:

  • methodName is present, is a string, and is not blank.

  • correlationData, if the payload carries it, is a string.

  • responseTopic, if the payload carries it, is a string.

  • A value present in both the payload and the MQTT 5 property agrees with its counterpart.

  • The reply address, whether it came from the payload field or from the MQTT 5 property, is a topic you can publish to: it contains neither # nor +, nor the null character U+0000.

  • The reply address encodes to at most 65535 bytes of UTF-8 and contains no unpaired surrogate.

  • correlationData fits in 65535 bytes. For correlationData from the MQTT 5 property, Edge counts the bytes themselves. For correlationData from the payload field, Edge counts their UTF-8 encoding, and the value also contains no unpaired surrogate.

  • The payload satisfies the tag’s generated schema, in five respects:

    • Every argument has the JSON type that the signature declares, or is null where the argument’s OPC UA type has a null value.

    • Every number lies inside the range of its OPC UA type.

    • A single value appears where the signature declares one, and an array where the signature declares an array.

    • Every name is one that a method of the object declares.

    • value is present.

If any one of these checks fails, Edge quarantines your request. Edge republishes the request on $invalid/ followed by the topic that you published to, and stops. The method does not run, and you get no response, not even on a reply address that you named.

Edge publishes your request to $invalid/, byte for byte. A client that subscribes to that topic receives the request. If no client subscribes, the request is gone. Edge assembles its own view of the request’s fields separately, and attaches that view only to the payload that Edge hands the adapter. Nothing of Edge’s appears in the quarantined copy. The quarantined copy carries no MQTT 5 Response Topic or Correlation Data property. Either property can be the reason for the refusal, so Edge does not copy it.

A request that reaches the method and fails

A request that passes every syntactic check reaches the method. Edge publishes a response to your reply address or to the mapping’s own topic:

The request fails Because The response carries

In Edge

The mapping does not have This mapping carries method calls selected, you name a method that the object does not have, name a method by a plain name that two methods share, give a malformed node id in methodName, send an argument that the named method does not declare, omit an argument that the method requires, use a type that Edge cannot encode, or send a whole number of magnitude 2^53 or more

value: null, an errorCode, and your correlationData, if present. The log also names what the object does offer.

On the device

The server refuses the call, or the method runs and reports a failure

value: null, an errorCode, and statusInfo if the device gives detail.

The two look the same to you. A refusal that Edge makes carries the same fields as a refusal that the device reports. You can therefore match responses to requests without knowledge of which side failed the request.

Three faults that are not reported

In three cases, Edge refuses a southbound write with no response and no quarantine:

  • The adapter is stopped.

  • There is no connection to the device.

  • The tag’s node id is malformed or names a namespace URI that the server does not publish.

For a method call, these three are the only refusals that produce neither a response nor a quarantine, apart from an internal error in Edge. They apply to every other southbound write as well, except that a write to a REFRESH tag never reads the tag’s node id. A value write never gets a response, so no refusal of a value write is reported, whatever its cause.

Status codes

Read errorCode as a name. It carries the OPC UA status code by name.

Code Numeric Meaning

Bad_MethodInvalid

0x80750000

The method id does not refer to a method of the object.

Bad_ArgumentsMissing

0x80760000

The request does not specify all input arguments.

Bad_InvalidArgument

0x80AB0000

One or more arguments are invalid.

Bad_NotExecutable

0x81110000

The method’s Executable attribute currently forbids the call.

If you receive Bad_NotExecutable, your request is correct. Retry it. Executable is a runtime attribute, so the same request can succeed later. A pump that refuses Start while interlocked reports exactly this.

The server can also refuse a call before it reaches the method. These codes are not specific to method calls:

Code Meaning

Bad_NodeIdUnknown

The object node does not exist on the server, or exists and is not an object.

Bad_UserAccessDenied

The session cannot call this method.

Bad_NotSupported

The server does not implement the Call service.

Edge also sends codes itself, without a call to the server:

  • Bad_MethodInvalid, Bad_ArgumentsMissing and Bad_InvalidArgument, for the refusals in A request that reaches the method and fails.

  • Bad_NodeIdUnknown, when the tag’s node is not a callable object.

  • Bad_SessionClosed, when the session that read the methods was replaced before the call. Edge did not send the call, so you can repeat the request.

  • Bad_UnexpectedError, when the server responds to the call without a result for it.

  • Bad_InternalError, when Edge cannot read the object’s methods, when it cannot verify the tag, and for a failure that carries no OPC UA status code.

Transport and session failures reach you unchanged, with the code that the failure carries.

Do not treat a timeout as proof that the method did not run. Edge knows that it sent the call, not what happened to the call. If you retry after a timeout, either make sure that the method is idempotent, or check the device’s state first.

If you name a reply address and nothing arrives

Several causes account for this.

First check whether Edge quarantined your request. Edge then publishes your original payload to $invalid/ followed by the topic that you publish to. To see the payload there, subscribe to that topic before you publish. The log names the check that the request failed: a JSON path for a schema failure, or a named fault for an unpublishable address or a missing method name.

Or the mapping does not read a reply address at all, and the response goes to the mapping’s own topic. Check the southbound Requests carry a response topic setting. A request that carries an address that the mapping does not read is valid, and Edge discards the address.

Or the tag has no northbound mapping, and nothing publishes a response at all.

Or the request met one of the three faults that are not reported.

Or the request arrived while Edge saved the mapping, or while the adapter started. See What a configuration change does to traffic.

Or you configured a Data Hub data policy that applies to the response and drops it. Edge then records the dropped message in its event log, at debug level, with the reason Policy prevented onward delivery of inbound PUBLISH.

What happens to a method call while its adapter restarts is unspecified.

We believe that this list of causes is complete, but we can have missed further corner cases.

Adapter lifecycle and limits

When an adapter is ready

This section is not normative. It describes how this version reports an adapter’s lifecycle, and that reporting can change in any release.

The OPC UA adapter writes a lifecycle line whenever its condition changes. Edge writes each line to the log and publishes it as an event in the event log, with the same text. Every line has four parts, separated by a semicolon and a space:

Lifecycle '<adapter>'; <identity>; <what just happened>; state now - value reads: <condition>, value writes: <condition>, method requests: <condition>
  • Lifecycle '<adapter>' lets you find the lines of one adapter with a plain text search.

  • The identity names the start of the adapter by its start time, and, where they apply, the connection and the session within that start.

  • What just happened is a short sentence. A fault starts with PROBLEM: and says whether the adapter recovers by itself.

  • The state now gives the condition of value reads, value writes and method requests:

Condition Meaning

working

Works.

starting (working with delays)

Method requests only. A method request works, but first reads its tag’s methods from the device, which can take long.

not working

Does not work. A value write that you send now is lost, without a response. A method request is lost too, or, while the session to the device is lost, gets a response with an errorCode.

none

Method requests only. The adapter has no method tag.

The last lifecycle line of an adapter tells you what works now. A connected adapter is not yet ready for method calls: Edge reports the connection first and reads the method signatures afterwards. When you see a line like this one, method calls are ready:

Lifecycle 'opcua-1'; start 2026-10-21T08:15:02.117Z, connection 1; read the methods of 3 of 3 method tags; state now - value reads: working, value writes: working, method requests: working

A start in bad weather can look like this. The device is unreachable at first, and the adapter retries by itself. It then connects, but cannot read the methods of the tag valve. Later the session to the device is lost:

Lifecycle 'opcua-1'; start 2026-10-21T08:15:02.117Z; starting; state now - value reads: not working, value writes: not working, method requests: not working
Lifecycle 'opcua-1'; start 2026-10-21T08:15:02.117Z, connection 1; PROBLEM: could not connect (attempt 1), see the preceding event. Retrying in 1043 ms by itself. A restart does not help; state now - value reads: not working, value writes: not working, method requests: not working
Lifecycle 'opcua-1'; start 2026-10-21T08:15:02.117Z, connection 1; connected, browse is ready; state now - value reads: working, value writes: working, method requests: starting (working with delays)
Lifecycle 'opcua-1'; start 2026-10-21T08:15:02.117Z, connection 1; PROBLEM: read the methods of 2 of 3 method tags. Not read, method requests to them read the methods first: 'valve'; state now - value reads: working, value writes: working, method requests: starting (working with delays)
Lifecycle 'opcua-1'; start 2026-10-21T08:15:02.117Z, connection 1; PROBLEM: session to the device lost. Waiting for it to resume; state now - value reads: not working, value writes: not working, method requests: not working
On a device slow to connect, the schema check might be absent

The schema check needs the tag’s generated schema, and Edge resolves that schema while the adapter starts. A device that has not responded yet has no schema to give. Edge then registers an empty schema and logs the fact:

Could not resolve the southbound schema for tag 'server' on adapter 'cas' after 36 attempts over 60481 ms. Writes to this tag will NOT be validated against its schema.

Edge shall resolve the schema again when you restart the adapter. The rule applies to every tag kind, not only to method tags.

An empty schema constrains nothing, so a valid request passes the schema check. Edge still refuses an invalid request, but the adapter makes the refusal, so Edge publishes a response instead of a quarantine:

With the schema Without the schema

Edge refuses the request before it touches the adapter, republishes your original payload on $invalid/, and names the JSON path in the log.

The adapter refuses the request. Edge publishes a response with value: null and an errorCode.

Edge’s own syntactic checks are unaffected, and so is the schema on your topic filter. A missing method name and an unpublishable reply address come from the request itself, not from the tag’s schema. Edge therefore still quarantines those faults.

What a configuration change does to traffic

This section describes what happens today. It is not a promise.

Any configuration change can restart the adapter, so what this section describes applies to any configuration change, not only to an explicit restart.

While Edge saves a mapping, requests that you publish to that mapping go nowhere. When Edge saves a southbound mapping, Edge removes the mapping’s subscription and registers it again, before it resolves the tag’s schema. A request that arrives before the subscription exists again matches no subscription, and Edge discards the request. Edge publishes nothing to $invalid/ and logs nothing against the request. A request that arrives while Edge resolves the schema waits, and Edge processes it once the mapping is ready.

The same holds while an adapter starts. Until Edge registers a method tag’s subscription, requests to its topic reach no subscription: the broker accepts the requests and Edge drops them.

If a request must not be lost, do not publish into a configuration change.

A response that you do not ask for can also arrive. A response goes to a topic like any other message, so every subscriber to that topic can receive it. Such subscribers include a subscriber that connects after the request, and every northbound mapping that you configure for the tag. After a configuration change, Edge can publish a response to an earlier request again. If a caller correlates by correlationData and matches responses to its own requests, such responses do not affect the caller.

Limits of this version
Limit What to do

Edge refuses a whole number of magnitude 2^53 or more, on a method argument and on an ordinary value write alike.

Nothing from the caller’s side. The limit is in the southbound path, not in the method. See Whole numbers of magnitude 2^53 or more.

Edge refuses an argument whose type is a union, or an abstract type.

Nothing in this version. A concrete type is needed for Edge to know what to encode.

The request schema states "any value" for an enumeration argument, and for an enumeration field inside a structure.

Nothing. Edge checks the value when it converts the argument, and publishes a refusal as a response.

The plain-name spelling is not available for a method whose name contains a semicolon.

Address the method by its full node id, for example ns=1;s=methodWith;Semicolon.

While the adapter has no connection to the device, Edge refuses a request with no response and no quarantine. While the session to the device is lost, Edge publishes a response with an errorCode.

Nothing. A refusal without a response names the connection state in the log only.

Edge discards a request that arrives while Edge saves its mapping, or while its adapter starts, with no response and no quarantine.

If a request must not be lost, do not publish into a configuration change.

What happens to a method call while its adapter restarts is unspecified.

Nothing.

The schema cannot state that an output is NaN or an infinity.

Read such an output as the string "NaN", "Infinity", or "-Infinity".

The request schema names every argument of every method on the object, unpaired.

Nothing. The adapter catches an argument that the named method does not declare.

Edge does not constrain the topic that a caller names in responseTopic.

Nothing. A request can name any topic that Edge can publish to.

Edge does not validate a response before Edge publishes it.

Validate a response yourself against the generated response schema.

OPC UA Authentication

HiveMQ Edge supports three authentication modes against OPC UA servers:

  • Anonymous (default): No authentication credentials required.

  • Basic: Username and password authentication.

  • X509: Certificate-based authentication using client certificates.

OPC UA Anonymous Authentication

When no auth configuration is provided, the adapter connects to the OPC UA server anonymously. This is the default behavior and is suitable for servers that do not require authentication.

Anonymous auth example (no auth block needed)
<opcua>
    <config>
        <uri>opc.tcp://opcua-server:4840</uri>
        <!-- No auth block = anonymous authentication -->
    </config>
</opcua>

OPC UA Basic Authentication

Basic auth example
<opcua>
    <config>
    ...
        <auth>
            <basic>
                <username>edge</username>
                <password>password</password>
            </basic>
        </auth>
    ...
    </config>
</opcua>
OPC UA Authentication X509
To use x509 authentication, the TLS configuration must be set and a keystore must be configured.
X509 auth example
<opcua>
    <config>
    ...
    <auth>
        <x509>
            <enabled>true</enabled>
        </x509>
    </auth>
    ...
    </config>
</opcua>

OPC UA TLS configuration

HiveMQ Edge supports connections to OPC UA servers with TLS and mutual TLS. To utilize mTLS, specify a keystore and enable x509 authentication.

A <keystore> is required by every security policy other than NONE, not only by x509 authentication. OPC UA identifies an application by the certificate it presents. An adapter configured for a secured policy without a keystore therefore never selects an endpoint, and it logs OPC UA Security policy '…​' for protocol adapter '…​' requires a keystore, cannot connect. Connect to an OPC UA server that uses a self-signed certificate walks through creating one.
Minimal TLS example using system truststore
<opcua>
    <config>
    ...
        <tls>
            <enabled>true</enabled>
        </tls>
    ...
    </config>
</opcua>
TLS example with mutual TLS and custom truststore
<opcua>
    <config>
    ...
        <tls>
            <enabled>true</enabled>
            <keystore>
                <path>/path/to/my/keystore.jks</path>
                <password>keystore-password</password>
                <privateKeyPassword>key-password</privateKeyPassword>
            </keystore>
            <truststore>
                <path>/path/to/my/truststore.jks</path>
                <password>truststore-password</password>
            </truststore>
        </tls>
    ...
    </config>
</opcua>

The following example shows what to do if the applicationUri cannot be derived from the certificate.

TLS example with mutual TLS, custom truststore and an explicit applicationUri
<opcua>
    <config>
    ...
        <applicationUri>urn:my-opcua-client</applicationUri>
        <tls>
            <enabled>true</enabled>
            <keystore>
                <path>/path/to/my/keystore.jks</path>
                <password>keystore-password</password>
                <privateKeyPassword>key-password</privateKeyPassword>
            </keystore>
            <truststore>
                <path>/path/to/my/truststore.jks</path>
                <password>truststore-password</password>
            </truststore>
        </tls>
    ...
    </config>
</opcua>
Table 19. Properties to configure TLS
Property Name Default Mandatory Description

enabled

false

Enables TLS encrypted connection

tlsChecks

STANDARD

Named certificate-validation preset. See the presets. Mutually exclusive with tlsChecksFull

tlsChecksFull

The six individual validation axes, for cases the presets do not cover. See Individual validation axes. Mutually exclusive with tlsChecks

keystore

Keystore configuration containing the client certificate including the chain. Required whenever the security policy is not NONE, and for X509 authentication

keystore > path

Path on the local file system to the keystore

keystore > password

Password to open the keystore

keystore > privateKeyPassword

Password to access the private key

truststore

System truststore

Truststore configuration containing trusted server certificates or trusted intermediates

truststore > path

Path on the local file system to the truststore

truststore > password

Password to open the truststore

allowList

Allow list of permitted server-certificate fingerprints. See Trusting self-signed certificates by fingerprint. Required when the effective trust mode is ALLOW_LIST, and never read under any other trust mode. An allow list configured where it cannot take effect is reported in a warning at start-up

allowList > path

Path on the local file system to the fingerprint allow list

revocationList

Certificate revocation lists used by revocation=CHECK and revocation=REQUIRE_CRLS. See Supplying certificate revocation lists. Needed whenever the certification path runs through a CA, and never read under a trust mode that builds no path. A revocation list configured where it cannot take effect is reported in a warning at start-up

revocationList > path

Path on the local file system to a CRL file, or to a directory of them. PEM or DER

Certificate validation

How strictly the adapter validates the certificate an OPC UA server presents is configured through exactly one of two mutually exclusive settings:

  • tlsChecks is a named preset. One value covers the common cases.

  • tlsChecksFull holds the six individual axes, for the cases a preset does not cover.

Setting both is a configuration error and the adapter refuses to start. If you already know your environment, Choosing a configuration maps it straight to the right setting.

From version 2026.13 onwards, tlsChecks additionally accepts SELF_SIGNED and NO_VERIFICATION, and tlsChecksFull, allowList and revocationList are available. Earlier versions offer only the NONE, APPLICATION_URI, STANDARD and ALL presets.

Nothing changes when you upgrade, and there is no migration to perform. Setting neither is the same as tlsChecks=STANDARD. The NONE, APPLICATION_URI, STANDARD and ALL values keep exactly the meaning they have always had. An existing configuration therefore validates certificates after the upgrade precisely as it did before. No configuration file needs editing and nothing is rewritten. The two new values, SELF_SIGNED and NO_VERIFICATION, and the tlsChecksFull axes only take effect where an operator asks for them.

A worked example starts from a refused connection and ends with data flowing. It generates a client certificate, has the server trust it, obtains the server’s fingerprint and configures the allow list. See Connect to an OPC UA server that uses a self-signed certificate.
Table 20. tlsChecks validation presets
Value Description

STANDARD

(Default.) The certificate must chain to a trust anchor, carry the expected OPC UA ApplicationUri, be within its validity period, and pass revocation checking. Where the path runs through a CA, revocation checking needs a revocation list to answer it.

ALL

As STANDARD, plus the endpoint hostname must appear in the certificate and the certificate must declare key usage permitting server authentication. The same revocation list requirement applies.

APPLICATION_URI

The certificate must chain to a trust anchor and carry the expected ApplicationUri. Nothing else is checked.

NONE

The certificate must chain to a trust anchor. Nothing else is checked. Note that this does not mean "no validation". See the warning below.

SELF_SIGNED

For environments with no CA. The certificate’s fingerprint must appear in the configured allow list, and it must carry the expected ApplicationUri, match the endpoint hostname, and be within its validity period. No CA, revocation infrastructure, or key-usage extensions are required.

NO_VERIFICATION

Nothing is verified: any certificate is accepted. See Accepting any server certificate.

tlsChecks=NONE does not disable certificate validation. The certificate must still chain to a trust anchor in the configured truststore or in the JVM’s cacerts bundle. NONE only switches off the checks applied on top of that. Configurations that set NONE expecting no validation at all fail to connect to servers with self-signed certificates. Use SELF_SIGNED, or NO_VERIFICATION if no verification really is intended.
Individual validation axes

tlsChecksFull exposes the six axes the presets are built from. Every axis is optional, and an omitted axis takes its strictest value. An empty tlsChecksFull therefore means maximum validation, and every relaxation is a visible, deliberate entry in the configuration file.

Axis Values Default Meaning

trustMode

CHAIN, ALLOW_LIST, ANY_CERT

CHAIN

How the certificate is established as trustworthy: by chaining to a trust anchor, by its fingerprint appearing in the allow list, or not at all.

sanUri

NONE, APPLICATION_URI

APPLICATION_URI

Whether the ApplicationUri announced by the server must match the SubjectAltName URI in its certificate.

hostname

NONE, HOSTNAME

HOSTNAME

Whether the endpoint hostname must match a SubjectAltName DNS name or IP address in the certificate.

validity

NONE, NOT_BEFORE_OR_AFTER

NOT_BEFORE_OR_AFTER

Whether the certificate’s validity period is enforced.

revocation

NONE, CHECK, REQUIRE_CRLS

REQUIRE_CRLS

How hard revocation status is enforced: CHECK demands that revocation status be determinable, REQUIRE_CRLS additionally demands a CRL for every issuing CA in the path. Requires trustMode=CHAIN. CHECK is not a best-effort mode: where no revocation information is available it fails exactly as REQUIRE_CRLS does. Both need a revocation list wherever the path contains a CA.

keyUsage

NONE, KEY_USAGE, SERVER_AUTH

SERVER_AUTH

How strictly the certificate’s declared purpose is enforced: KEY_USAGE requires the KeyUsage extension to be present and appropriate, SERVER_AUTH additionally requires an ExtendedKeyUsage permitting server authentication.

Unless overrideUri is set, the hostname check validates the host of the endpoint URL the server advertises during discovery, which can differ from the host in the configured <uri>.
Omit an axis you do not want to set. Do not leave its element empty. An empty element that is not the first one in the block is read as unset, which is the same as omitting it, by luck of position. An empty first element collapses the whole tlsChecksFull block into the concatenated text of the axes that follow it. Which value belonged to which axis is then unrecoverable. The adapter refuses to start rather than guess, and the start-up message quotes back the text it found. The axes hold only validation settings, so repeating them is safe and tells you what to correct. An empty <tlsChecksFull/> is a different thing and is perfectly valid: it means maximum validation. The same collapse applies one element up. An empty first child of <tls> itself, for example <enabled></enabled>, collapses the whole tls element, and the adapter’s configuration is rejected with "The 'tls' configuration could not be read". On a reload, a running instance is left unchanged. A bare <tls/> is valid and means TLS is disabled. <keystore> and <truststore> behave the same way. An empty first child collapses the element and the configuration is rejected with "The 'truststore' configuration could not be read". A bare <keystore/> or <truststore/> is valid and means the store is not configured.
For tls, keystore and truststore the message names the element and the mistake but deliberately does not repeat the text it collapsed into. A collapse concatenates the text of everything nested inside the element. For a store that text is typically the store password, and for tls it can be both stores' passwords at once. Since this message is written to the log with a stack trace, repeating it would copy credentials into log files, log aggregation and support bundles. Which element each value belonged to is unrecoverable in any case, so the text would not tell you what to fix. The element name and the empty first child do.
Under trustMode=CHAIN, keyUsage=NONE does not suppress a failure when the certificate marks its KeyUsage or ExtendedKeyUsage extension critical. The underlying OPC UA stack enforces a critical extension regardless of the checks configured, so such a certificate is still refused with Bad_CertificateUseNotAllowed. The same applies to tlsChecks=NONE and to every other preset that builds a chain. Under trustMode=ALLOW_LIST and trustMode=ANY_CERT the axis is honoured exactly as written.
The configuration file accepts these values case-insensitively and with the underscores optional, so any_cert and ANY_CERT both select the same trust mode. That tolerance exists so configurations written for earlier versions keep working. It is not a second spelling to adopt. The REST API and the UI accept only the exact values listed above, and reject anything else naming the offending setting and the values it permits. Write the exact spelling everywhere, and a configuration stays portable between the file, the API and the UI.
A value the adapter does not recognise is a configuration error. That covers a misspelling and a value taken from a different setting. The adapter is refused rather than started with different certificate validation than was written, and the error names the offending value together with the permitted ones. The same applies to a setting name the model does not have, such as <tlsCheks>. Certificate-validation settings are never silently dropped or replaced with a default. The preset door’s default is STANDARD, which checks less than ALL, so "treat a typo as unset" would be able to weaken validation. During a configuration reload the rejection is confined to the affected adapter, and every other adapter is refreshed as usual. Where the rejection surfaces depends on the mistake. A misspelled value, and a misspelled enclosing element such as <tlls> or <securtiy>, mean the new configuration cannot be read at all. Such a configuration is refused as it is loaded, and a running instance keeps the configuration it already had. A misspelled name inside the tls block, such as <tlsCheks> or an axis written <trustmode>, is carried through instead and refuses the adapter at start, leaving it visibly in error until the entry is corrected. The entry is preserved when the configuration is written back out, so an unrelated edit through the UI or API cannot silently delete the misspelling and leave the adapter running under a default nobody chose.
Table 21. Each preset expressed as axes
Preset trustMode sanUri hostname validity revocation keyUsage

STANDARD

CHAIN

APPLICATION_URI

NONE

NOT_BEFORE_OR_AFTER

REQUIRE_CRLS

NONE

ALL

CHAIN

APPLICATION_URI

HOSTNAME

NOT_BEFORE_OR_AFTER

REQUIRE_CRLS

SERVER_AUTH

APPLICATION_URI

CHAIN

APPLICATION_URI

NONE

NONE

NONE

NONE

NONE

CHAIN

NONE

NONE

NONE

NONE

NONE

SELF_SIGNED

ALLOW_LIST

APPLICATION_URI

HOSTNAME

NOT_BEFORE_OR_AFTER

NONE

NONE

NO_VERIFICATION

ANY_CERT

NONE

NONE

NONE

NONE

NONE

Revocation status can only be determined while a certification path is being built. Combining revocation other than NONE with trustMode=ALLOW_LIST or ANY_CERT is therefore rejected at start-up rather than silently ignored. Because the axis defaults to REQUIRE_CRLS, a tlsChecksFull that sets trustMode to ALLOW_LIST or ANY_CERT must also set revocation to NONE explicitly.
When no <truststore> element is present, trustMode=CHAIN falls back to the JVM’s cacerts bundle, so a certificate signed by a public CA needs no truststore of its own. A self-signed certificate that chains to nothing does need one, which is what SELF_SIGNED and NO_VERIFICATION exist for. A public CA is an issuing CA like any other, so the default preset still needs that CA’s CRL. See Supplying certificate revocation lists.
Leaving the element out is how "use the JVM cacerts`" is written. A `<truststore> that is present must name a usable file. A missing <path>, or one whose value is empty or only whitespace, stops the adapter with Truststore is configured but has no 'path'. It does not quietly fall back to cacerts, because a configuration claiming a truststore while the adapter trusted every public CA is exactly the mismatch this refusal exists to prevent. <keystore> follows the same rule, where an empty path would otherwise mean no client certificate and surface much later as a failed handshake.
When a chain-building configuration runs without the hostname check, the adapter logs a warning once at start-up. The certificate is trusted via its chain but is not verified to belong to this endpoint, so a substituted server whose certificate chains to the same anchor would be accepted. Enable the check with tlsChecks=ALL or tlsChecksFull.hostname=HOSTNAME.
Table 22. Choosing a configuration
Environment Setting

Server certificate placed in the truststore, so that it is its own trust anchor

tlsChecks=STANDARD

The same, where the certificate also names its host and declares server-authentication key usage

tlsChecks=ALL

Any chain with an issuing CA, whether public CA, corporate PKI or private CA

tlsChecks=STANDARD plus a revocationList carrying that CA’s CRL

The same, where the CA publishes no CRLs at all

tlsChecksFull with trustMode=CHAIN, revocation=NONE

Self-signed per-device certificates, no CA

tlsChecks=SELF_SIGNED

Self-signed certificates that carry no hostname

tlsChecksFull with trustMode=ALLOW_LIST, hostname=NONE, revocation=NONE, keyUsage=NONE

No verification possible or wanted, MITM risk accepted

tlsChecks=NO_VERIFICATION

Supplying certificate revocation lists

Revocation asks one question: has this issuer withdrawn this certificate? Only the issuing CA can answer it, and it answers by publishing a certificate revocation list. The adapter is given that list through the <revocationList> element:

<opcua>
    <config>
        <tls>
            <enabled>true</enabled>
            <tlsChecks>STANDARD</tlsChecks>
            <truststore>
                <path>/opt/hivemq/conf/opcua-truststore.jks</path>
                <password>changeit</password>
            </truststore>
            <revocationList>
                <path>/opt/hivemq/conf/opcua-crls</path>
            </revocationList>
        </tls>
        ...
    </config>
</opcua>

The path may be a single CRL file or a directory of them, in PEM or DER. A PKI that publishes one CRL per issuing CA is the common case, so pointing at a directory avoids concatenating them by hand. Every CRL under the path applies to whichever issuer signed it.

Like the fingerprint allow-list, the file is read once when the adapter starts and never written, so it can be a read-only artifact. Refreshing a CRL means restarting the adapter.

A path through a CA needs a CRL. A directly trusted certificate does not. Revocation status is determined while the certification path is built, from the CRLs supplied here. Where the path contains an issuing CA and no CRL covers it, that status is unknown. Unknown fails closed, as Bad_CertificateRevocationUnknown, no matter how correct the rest of the configuration is.

Because revocation defaults to REQUIRE_CRLS, this applies to the default STANDARD preset and to ALL. A CA in the truststore with no <revocationList> configured is therefore reported at start-up:

revocation=REQUIRE_CRLS is enforced and the truststore contains a CA, but no certificate revocation
list is configured. The issuer's revocation status is therefore unknown, and unknown fails closed [...]

Deployments with no issuing CA in the path are unaffected and need no CRL:

  • A server certificate placed in the truststore itself is the trust anchor. Nothing issued it, so nothing can revoke it, and STANDARD connects normally.

  • SELF_SIGNED, NO_VERIFICATION and APPLICATION_URI resolve to revocation=NONE.

The start-up warning is raised from the truststore alone, before any server has been contacted. It therefore cannot tell an issuing CA apart from a self-signed server certificate that declares basicConstraints CA:TRUE, and some device certificates do. If yours is one of those, the warning appears and the connection nevertheless succeeds, because no issuer ever enters the path. Treat the warning as the reason to check for a CRL, not as evidence that the connection will fail.

Where a CA genuinely publishes no CRLs, set revocation to NONE through the axes. That is a deliberate, visible entry in the configuration file, which is the point. The check is switched off on purpose rather than passing by accident.

A <revocationList> is never read under a trust mode that builds no certification path, which means ALLOW_LIST or ANY_CERT. Such a configuration is reported in a warning at start-up. A path that cannot be read, or that holds no CRLs, stops the adapter with a message naming the file, rather than quietly leaving revocation unchecked.
Diagnosing a refused connection

A refused connection carries an OPC UA status code. A failed trust decision reports Bad_SecurityChecksFailed, and the specific cause is in the message that accompanies it. A failed identity or hygiene check reports its own status code instead. The first row is the exception: it arrives before any certificate has been seen at all.

Status code or message Cause and remedy

Bad_ConfigurationError: no endpoint selected

No endpoint offered by the server matches the configured security policy and message security mode. Most often a secured security > policy is configured without a <keystore>. A WARN naming the policy that requires a keystore immediately precedes this error. Provide a keystore, or align the policy and messageSecurityMode with an endpoint the server offers.

Bad_SecurityChecksFailed: unable to find valid certification path to requested target

The server certificate does not chain to anything in the truststore, or in the JVM cacerts when no truststore is configured. That is the usual case for a self-signed device certificate. Add its issuer to a truststore, or trust the certificate by fingerprint with tlsChecks=SELF_SIGNED.

Bad_SecurityChecksFailed: server certificate fingerprint is not in the configured allow-list

The certificate presented is not one of the trusted fingerprints. The rejection log names the fingerprint that was seen. Add it if you recognise the server. If you did not change anything, the server’s certificate has been replaced. Find out why before adding it.

Bad_CertificateHostNameInvalid

The endpoint hostname does not appear in the certificate. Either correct the endpoint URI, or drop the check with tlsChecksFull.hostname=NONE if the device certificates carry no hostname.

Bad_CertificateUriInvalid

The ApplicationUri the server announces does not match the SubjectAltName URI in its certificate. Factory device certificates frequently carry a SAN URI that was never aligned with the announced URI. Correct one to match the other, or drop the check with tlsChecksFull.sanUri=NONE.

Bad_CertificateUseNotAllowed

The certificate lacks the KeyUsage or ExtendedKeyUsage extensions the configuration demands. Device certificates frequently omit these. tlsChecksFull.keyUsage=NONE, or the SELF_SIGNED preset, does not require them. Under trustMode=CHAIN that relaxation does not apply to a certificate that marks the extension critical. See the note on the axes table.

Bad_CertificateTimeInvalid

The certificate is expired or not yet valid. Replace it, or relax tlsChecksFull.validity if the deployment genuinely cannot maintain certificate lifetimes.

Bad_CertificateRevocationUnknown, Bad_CertificateIssuerRevocationUnknown

Revocation status could not be determined for a CA in the path, which fails closed. Almost always no CRL covers that CA, so supply one through revocationList. The adapter warns about this at start-up, before the connection is attempted. Where the CA publishes no CRLs at all, set revocation to NONE through the axes. CHECK does not help, because it fails the same way.

A configuration mistake stops the adapter from starting rather than producing a connection error. The mistakes that do this are: a misspelled value or setting name; both settings at once; an axis element, or the first element of the tls, keystore or truststore block, left empty; a keystore or truststore whose path is missing or empty; an allow list or revocation list that cannot be read; and revocation without a chain. The reason is logged with the resolution named.
Trusting self-signed certificates by fingerprint

Factory networks often have no CA. Every device presents its own self-signed certificate, which chains to nothing a public CA bundle knows about.

Chain validation is not impossible in that situation. A self-signed certificate placed in the truststore is its own trust anchor, so trustMode=CHAIN will accept it. What that costs is a truststore holding one certificate per machine, exported from each device and redistributed to every HiveMQ Edge instance whenever a device is replaced or its certificate rotated.

Fingerprints are the lighter answer to the same problem. Instead of a trust anchor, the adapter can be given the SHA-256 fingerprints of the specific certificates it should accept. A fingerprint is short enough to send by email or read out over the phone, and it deploys as a read-only file.

The allow list is a plain text file. It holds one fingerprint per line, in hexadecimal, with : separators optional and case ignored. A # starts a comment.

# machine 1, fingerprint supplied by the device vendor
9f:86:d0:81:88:4c:7d:65:9a:2f:ea:a0:c5:5a:d0:15:a3:bf:4f:1b:2b:0b:82:2c:d1:5d:6c:15:b0:f0:0a:08

# machine 2
b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
<opcua>
    <config>
        <tls>
            <enabled>true</enabled>
            <tlsChecks>SELF_SIGNED</tlsChecks>
            <allowList>
                <path>/opt/hivemq/conf/opcua-fingerprints.txt</path>
            </allowList>
        </tls>
        ...
    </config>
</opcua>
Obtaining a fingerprint

There are three practical ways to get the value that goes in the file:

  • From the device vendor. A fingerprint is short enough to send by email or read out over the phone. This is what makes the approach workable when no CA exists and certificates are awkward to export.

  • From a certificate you already have, with OpenSSL:

    openssl x509 -in server-cert.pem -noout -fingerprint -sha256

    Both the colon-separated output of this command and the same value without separators are accepted.

  • From the log. Start the adapter with the intended server unlisted. The rejection logs the fingerprint the server presented, in the format the file accepts. Only do this where you can be sure no attacker is interposed, because at that moment nothing has verified the certificate.

Behavior

The file is read once at adapter start and never written to. There is no trust-on-first-use. A fingerprint is trusted only because an operator put it there, so a certificate presented during the first connection cannot enrol itself. This also means the file can be deployed as a read-only secret. After editing the file, restart the adapter for the change to take effect. The running adapter keeps the set it read at start.

When a server presents a certificate that is not on the list, the connection is refused. The fingerprint that was seen is written to the log, together with the certificate’s subject and issuer, in the format the file accepts. An operator who recognises the server can add that line without having to extract the certificate first.

The allow list is a trust set, not per-endpoint pinning. The adapter accepts any certificate whose fingerprint appears in its file, and a file with several entries trusts all of them on every adapter that uses it. Unlike accepting any certificate, this detects a listed certificate being replaced by an unlisted one. If a device’s certificate is rotated, the fingerprint no longer matches and the connection fails until the new fingerprint is added deliberately. It does not tell the listed certificates apart. A different machine whose certificate is also in the file passes the trust decision, and only the identity checks (sanUri, hostname) can distinguish it. When single-certificate pinning is the goal, give each adapter its own allow-list file containing exactly the one fingerprint that adapter should accept. This matters most when hostname or sanUri validation has been relaxed.

What it does not do is establish that the certificate was genuine in the first place. The allow list closes the change-detection gap, not the first-contact one. Whoever writes the file trusts the channel that delivered the fingerprint: the vendor’s email, a phone call, a device label. This is the same limitation as the first ssh connection to a new host. Treat the fingerprint with the care you would give the certificate itself.

The adapter refuses to start, naming the problem, if the allow list is missing when the trust mode requires one, if the file cannot be read, or if it contains no fingerprints. A malformed line fails the whole file rather than being skipped. Silently dropping a mistyped entry would shrink the allow list without telling anyone, leaving an operator to debug a refused connection whose entry is plainly visible in the file.

The SELF_SIGNED preset also requires the certificate to match the endpoint hostname. Device certificates that carry only an ApplicationUri and no DNS name or IP address fail that check. For those, use tlsChecksFull with trustMode=ALLOW_LIST, hostname=NONE, revocation=NONE and keyUsage=NONE. The last two must be explicit because each omitted axis takes its strictest value. Revocation checking requires a certification path that ALLOW_LIST does not build, and such device certificates typically carry no key-usage extensions either.
Accepting any server certificate

tlsChecks=NO_VERIFICATION accepts whatever certificate a server presents, without establishing any trust in it:

<opcua>
    <config>
        <tls>
            <enabled>true</enabled>
            <tlsChecks>NO_VERIFICATION</tlsChecks>
        </tls>
        ...
    </config>
</opcua>

Individual checks can still be switched back on through tlsChecksFull. The following accepts any certificate but insists it carries the expected ApplicationUri:

<opcua>
    <config>
        <tls>
            <enabled>true</enabled>
            <tlsChecksFull>
                <trustMode>ANY_CERT</trustMode>
                <sanUri>APPLICATION_URI</sanUri>
                <hostname>NONE</hostname>
                <validity>NONE</validity>
                <revocation>NONE</revocation>
                <keyUsage>NONE</keyUsage>
            </tlsChecksFull>
        </tls>
        ...
    </config>
</opcua>
A deployment accepting any certificate is vulnerable to man-in-the-middle attacks. An interposing server is indistinguishable from the intended one. The identity checks assert only which server a certificate claims to be, not that the certificate is genuine. An attacker able to present any certificate can present one carrying the expected ApplicationUri and hostname. To keep this from going unnoticed, the adapter logs a warning at start-up and again on every successful connection, naming the adapter and the endpoint. The warnings fire whenever a certificate can actually be accepted, which means TLS enabled and a security policy other than NONE. Under policy NONE no certificate authenticates the connection at all, so nothing is logged about certificates that are never examined. Prefer SELF_SIGNED, which costs one fingerprint per server and closes this gap.

OPC UA Security Configuration

The OPC UA adapter supports various security policy / message security mode combinations depending on the server it has to talk to.

In versions 2025.17 and before, the adapter selected the first endpoint matching the configured security policy without considering the message security mode.

From version 2025.18 onwards, messageSecurityMode can be explicitly configured to disambiguate when an OPC UA server exposes multiple endpoints under the same security policy. When messageSecurityMode is left at its default value IGNORED, the adapter picks a sensible mode based on the policy: NONE for policy NONE, otherwise SIGN_AND_ENCRYPT.

Example security configuration
<opcua>
    <config>
    ...
        <security>
            <policy>BASIC128RSA15</policy>
            <messageSecurityMode>SIGN_AND_ENCRYPT</messageSecurityMode>
        </security>
    ...
    </config>
</opcua>
Table 23. Properties to configure OPC UA Security
Property Name Default Mandatory Values Description

policy

NONE

NONE, BASIC128RSA15, BASIC256, BASIC256SHA256, AES128_SHA256_RSAOAEP, AES256_SHA256_RSAPSS

General security policy used for message exchange

messageSecurityMode

IGNORED

IGNORED, NONE, SIGN, SIGN_AND_ENCRYPT

Message security mode used for message exchange. The default IGNORED lets the adapter pick a sensible value based on the configured policy: NONE for policy NONE, otherwise SIGN_AND_ENCRYPT. Set explicitly to disambiguate when an OPC UA server exposes multiple endpoints under the same security policy.

BASIC128RSA15 and BASIC256 are deprecated security policies and should only be used if required by legacy OPC UA servers. For new deployments, use BASIC256SHA256, AES128_SHA256_RSAOAEP, or AES256_SHA256_RSAPSS.
A value the adapter does not recognise in either setting, and a child element <security> does not have, refuse the adapter’s configuration naming the mistake and the permitted values. Neither is resolved to a default. This matters most for messageSecurityMode, where the default IGNORED means "let the policy decide". A misspelling read as IGNORED under policy=NONE would select message security NONE and connect unsigned and unencrypted. The correctly spelled SIGN matches no endpoint at all and refuses to connect. Values are matched case-insensitively and underscores are optional, so SignAndEncrypt and SIGN_AND_ENCRYPT are the same value. Leaving the element empty and omitting it both mean IGNORED.

OPC UA Supported Data Types

The OPC UA adapter supports the following data types for both northbound (reading from OPC UA) and southbound (writing to OPC UA) operations:

Table 24. Supported OPC UA Data Types
JSON Type Description OPC UA Types

boolean

Boolean values (true/false)

Boolean

integer

Integer numeric values

Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64

number

Floating-point numeric values

Float, Double

string

Text values

String, LocalizedText, ByteString

date-time

Date and time values (ISO 8601 format)

DateTime

array

Arrays of the above types

Arrays of any supported type

object

Complex structured data

ExtensionObject, QualifiedName, NodeId

The adapter automatically converts between OPC UA data types and their JSON representations when publishing to MQTT (northbound) or writing to OPC UA nodes (southbound).

S7 Adapter

The S7 adapter enables connections to Siemens S7 PLCs (Programmable Logic Controllers). The adapter supports reading S7 tags and data blocks from S7-300, S7-400, S7-1200, S7-1500, and LOGO series controllers.

The adapter supports the following capability:

  • Read (Northbound): Poll S7 tags and data blocks and publish data to MQTT topics.

The S7 protocol also uses the term "tags". These S7 tags are different from HiveMQ Edge tags. In this documentation, we refer to them as S7 tags when discussing PLC addressing.
S7 PUT/GET must be enabled on the PLC, otherwise a connection with the S7 adapter is not possible. The setting can be found in your TIA Portal in the General tab, under Protection & Security → Connection mechanisms → Permit access with PUT/GET communication from remote partner.
Example minimal S7 adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-s7-protocol-adapter</adapterId>
            <protocolId>s7</protocolId>
            <config>
                <host>my.s7-device</host>
                <port>102</port>
                <controllerType>S7_1500</controllerType>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>motor/speed</topic>
                    <tagName>motor_speed</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>motor_speed</name>
                    <description>The speed of the moto</description>
                    <definition>
                        <tagAddress>%ID103</tagAddress>
                        <dataType>DINT</dataType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

S7 Adapter Properties (config)

Table 25. S7 Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

host

The host or IPv4/IPv6 of the S7 device.

Hostname or IP

port

102

The port to which the adapter connects.

Integer 1-65535

controllerType

S7_300

The series of the S7 PLC.

S7_300, S7_400, S7_1200, S7_1500, LOGO

remoteRack

0

Rack value for the remote main CPU.

Integer

remoteSlot

0

Slot value for the remote main CPU.

Integer

remoteRack2

0

Rack value for the remote secondary CPU.

Integer

remoteSlot2

0

Slot value for the remote secondary CPU.

Integer

remoteTsap

0

Remote TSAP (Transport Services Access Point) value. Usually required only for PLCs from the LOGO series.

Integer

keepAlive

false

Enable keep-alive ping to prevent TCP timeouts. Recommended when polling interval exceeds 7 seconds. Automatically enabled if polling interval is >= 7000ms.

Boolean

s7ToMqtt

Configuration for S7 to MQTT data flow

s7ToMqtt

S7 Northbound config

Table 26. S7 to MQTT (Northbound) (s7ToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries.

Integer >= -1

publishChangedDataOnly

true

When enabled, the adapter only publishes data when a value has changed since the last poll. This reduces MQTT traffic for slow-changing data.

Boolean

S7 Tag Definition

Tags in the S7 adapter define which PLC addresses to read.

Table 27. S7 Tag Definition Properties
Property Name Default Mandatory Description Format

tagAddress

The address of the S7 tag to read. See S7 Tag Address for format.

String

dataType

The data type of the tag value. See S7 Types for supported types.

Enum

S7 Tag Address

The general structure of tags is defined identically for each protocol adapter as described in Tags. The precise definition is different as listed below. In the following the S7 tags addresses are described. The S7 tag address for an S7 variable can be found in TIA Portal.

PLC (Programmable Logic Controllers) Tags

The address for tags can be found in TIA Portal in the Address column of the PLC Tags table . For PLC tags, this value can be used as it is directly in HiveMQ Edge.

a27cd79f e6f6 4632 b949 b7484213a102

If you cannot get the addresses directly from TIA Portal, you can use the following format to construct the address:

Format for bit addresses:

%<Memory-Area-Code><Byte-Offset>.<Bit-Offset>

Format for byte addresses

%<Memory-Area-Code><Memory-Size-Code><Byte-Offset>

Example: %I205.0 or ´ %QB207

Where the Memory-Area-Code is one of I(Inputs), Q(Outputs), D(Direct peripheral access), M(Markers), C(Counter), T(Timer), DB(Data block).

And Memory-Size-Code describes the size of the variable value. The codes are X(1 bit or 8 bytes), B(1 byte), W(2 bytes), D(4 bytes).
For detailed information on which code maps to which type, see S7 Types.

Data blocks

The data block addressing scheme is:

%DB<Data-Block-Number>:<Byte-Offset>.<Bit-Offset>

%DB<Data-Block-Number>:<Byte-Offset>

Example: %DB10:20.0 or %DB10:22

The Data-Block-Number is displayed in the tree view on the left in your TIA Portal, behind the name of your data block, enclosed in [] brackets or on the top of the data block view.

The Byte-Offset (and Bit-Offset) can be found in TIA Portal in the Offset column in the data block view

13030c6c b52d 4112 a461 48961f655cfa
Fixed offsets are only available for variables in data blocks if Optimized block access is turned off.

The setting for optimizing block access can be found in the properties of the data block in TIA Portal.

e06d9b94 ae36 4b51 9a84 2bc7278fd4e2

S7 Types

Type Description Memory size code MQTT payload example Value range

BOOL

1 bit

X

{"value": true}

true/false

BYTE

1 byte unsigned

B

{"value": 255}

0-255

SINT

1 byte signed

B

{"value": -75}

-128-127

USINT

1 byte unsigned

B

{"value": 255}

0-255

INT

2 byte signed

W

{"value": -3450}

-32768-32767

UINT

2 byte unsigned

W

{"value": 3450}

0-65535

DINT

4 byte signed

D

{"value": -3450}

-2147483648-2147483647

UDINT

4 byte unsigned

D

{"value": 123232}

0-4294967295

LINT

8 byte signed

X

{"value": -123232000}

-9223372036854775808-9223372036854775807

ULINT

8 byte unsigned

X

{"value": 123232000}

0-18446744073709551615

WORD

2 byte unsigned

W

{"value": 1024}

0-65535

DWORD

4 byte unsigned

D

{"value": 123456789}

0-4294967295

LWORD

8 byte unsigned

X

{"value": 1234567890000}

0-18446744073709551615

REAL

4 byte floating point signed

D

{"value":123.456789} or {"value":3.4028235E38}

1.4E-45-3.4028235E38

LREAL

8 byte floating point signed

X

{"value":123.456789} or {"value":4.9E-324}

4.9E-324-1.7976931348623157E308

CHAR

1 byte character

B

{"value":"a"}

ascii alphabet

WCHAR

2 byte character

W

{"value":"a"}

unicode alphabet

STRING

ascii string

X

{"value":"abcdefgh"}

ascii alphabet

WSTRING

unicode string

X

{"value":"abcdefgh"}

unicode alphabet

TIME

4 byte signed, millisecond duration

D

{"value":-1234}

-2147483648-2147483647

LTIME

8 byte signed, nanosecond duration

D

{"value":-1234}

-9223372036854775808-9223372036854775807

DATE

Date

X

{"value":"2020-03-12"}

(ISO 8601) "1990-01-01"-"2168-12-31"

TIME_OF_DAY

Time of day milliseconds

X

{"value":"01:23:45.678"}

(ISO 8601) "00:00:00.000"-"23:59:59.999"

LTIME_OF_DAY

Time of day nanoseconds

X

{"value":"01:23:45.678901234"}

(ISO 8601) "00:00:00.000"-"23:59:59.999999999"

DATE_AND_TIME

DateTime milliseconds

X

{"value":"2020-03-12"}

(ISO 8601) 1970-01-01T00:00:00.000-2089-12-31T23:59:59.999

LDATE_AND_TIME

DateTime nanoseconds

X

{"value":"2020-03-12T23:59:59.123456789"}

(ISO 8601) 1970-01-01T00:00:00.000-2089-12-31T23:59:59.999

ADS / TwinCAT Adapter

The ADS adapter enables connections to Beckhoff and other TwinCAT 3 capable PLCs using the ADS (Automation Device Specification) protocol.

The adapter supports the following capability:

  • Read (Northbound): Poll ADS variables and publish data to MQTT topics.

Example minimal ADS adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-ads-protocol-adapter</adapterId>
            <protocolId>ads</protocolId>
            <config>
                <host>my.ads-server.com</host>
                <port>1234</port>
                <targetAmsPort>123</targetAmsPort>
                <sourceAmsPort>124</sourceAmsPort>
                <targetAmsNetId>1.2.3.4.5.6</targetAmsNetId>
                <sourceAmsNetId>1.2.3.4.5.7</sourceAmsNetId>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <tagName>tag-name</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag-name</name>
                    <description>description</description>
                    <definition>
                        <tagAddress>123</tagAddress>
                        <dataType>BOOL</dataType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>
Example full ADS adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-ads-protocol-adapter</adapterId>
            <protocolId>ads</protocolId>
            <config>
                <host>my.ads-server.com</host>
                <port>1234</port>
                <targetAmsPort>1234</targetAmsPort>
                <sourceAmsPort>12345</sourceAmsPort>
                <targetAmsNetId>1.2.3.4.5.6</targetAmsNetId>
                <sourceAmsNetId>1.2.3.4.5.7</sourceAmsNetId>
                <adsToMqtt>
                    <pollingIntervalMillis>10</pollingIntervalMillis>
                    <maxPollingErrorsBeforeRemoval>9</maxPollingErrorsBeforeRemoval>
                    <publishChangedDataOnly>false</publishChangedDataOnly>
                </adsToMqtt>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <maxQos>1</maxQos>
                    <includeTagNames>true</includeTagNames>
                    <includeTimestamp>true</includeTimestamp>
                    <messageHandlingOptions>MQTTMessagePerSubscription</messageHandlingOptions>
                    <tagName>tag-name</tagName>
                    <mqttUserProperties>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value1</value>
                        </mqttUserProperty>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value2</value>
                        </mqttUserProperty>
                    </mqttUserProperties>
                </northboundMapping>
                <northboundMapping>
                    <topic>my/topic/2</topic>
                    <maxQos>1</maxQos>
                    <includeTagNames>true</includeTagNames>
                    <includeTimestamp>true</includeTimestamp>
                    <messageHandlingOptions>MQTTMessagePerSubscription</messageHandlingOptions>
                    <tagName>tag-name</tagName>
                    <mqttUserProperties>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value1</value>
                        </mqttUserProperty>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value2</value>
                        </mqttUserProperty>
                    </mqttUserProperties>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag-name</name>
                    <description>description</description>
                    <definition>
                        <tagAddress>123</tagAddress>
                        <dataType>WORD</dataType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

ADS Adapter Properties (config)

Table 28. ADS Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

host

The host or IPv4/IPv6 of the ADS device.

Hostname or IP

port

48898

The TCP port to connect to.

Integer 1-65535

targetAmsNetId

The AMS Net ID of the device to connect to (6 octets).

String (e.g., 192.168.1.1.1.1)

targetAmsPort

851

The AMS port number on the device to connect to. Typical TwinCAT runtime port is 851.

Integer 1-65535

sourceAmsNetId

The AMS Net ID used by HiveMQ Edge (6 octets).

String (e.g., 192.168.1.2.1.1)

sourceAmsPort

48898

The local AMS port number used by HiveMQ Edge.

Integer 1-65535

keepAlive

false

Enable TCP keep-alive to maintain connection during inactivity.

Boolean

adsToMqtt

Configuration for ADS to MQTT data flow

adsToMqtt

ADS Northbound config

Table 29. ADS to MQTT (Northbound) (adsToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries.

Integer >= -1

publishChangedDataOnly

true

When enabled, the adapter only publishes data when a value has changed since the last poll. This reduces MQTT traffic for slow-changing data.

Boolean

ADS Tag Definition

Tags in the ADS adapter define which PLC variables to read.

Table 30. ADS Tag Definition Properties
Property Name Default Mandatory Description Format

tagAddress

The ADS address of the variable to read. See ADS Tag Address for format.

String

dataType

The data type of the variable. See ADS Types for supported types.

Enum

ADS Tag Address

The general structure of tags is defined identically for each protocol adapter as described in Tags. The precise definition is different as listed below. In the following the S7 tags addresses are described. The ADS tag address is the program name followed by the variable name separated by a dot, in the format: <program-name>.<variable-name> .

Example program:

PROGRAM MAIN
VAR
    iCounter          : INT     := 41;
    MiCounter AT %MW2 : INT     := 21;
    QstrText AT %QB20 : STRING  := 'abcdefg';
END_VAR

The variable addresses for the protocol adapter are then:

  • MAIN.iCounter

  • MAIN.MiCounter

  • MAIN.QstrText

ADS Types

Type Description MQTT payload example Value range

BOOL / BIT

1 bit

{"value": true}

true/false

BYTE

1 byte unsigned

{"value": 255}

0-255

SINT

1 byte signed

{"value": -75}

-128-127

USINT

1 byte unsigned

{"value": 255}

0-255

INT

2 byte signed

{"value": -3450}

-32768-32767

UINT

2 byte unsigned

{"value": 3450}

0-65535

DINT

4 byte signed

{"value": -3450}

-2147483648-2147483647

UDINT

4 byte unsigned

{"value": 123232}

0-4294967295

LINT

8 byte signed

{"value": -123232000}

-9223372036854775808-9223372036854775807

ULINT

8 byte unsigned

{"value": 123232000}

0-18446744073709551615

WORD

2 byte unsigned

{"value": 1024}

0-65535

DWORD

4 byte unsigned

{"value": 123456789}

0-4294967295

LWORD

8 byte unsigned

{"value": 1234567890000}

0-18446744073709551615

REAL

4 byte floating point signed

{"value":123.456789} or {"value":3.4028235E38}

1.4E-45-3.4028235E38

LREAL

8 byte floating point signed

{"value":123.456789} or {"value":4.9E-324}

4.9E-324-1.7976931348623157E308

STRING

ascii string

{"value":"abcdefgh"}

ascii alphabet

WSTRING

unicode string

{"value":"abcdefgh"}

unicode alphabet

TIME

4 byte unsigned, millisecond duration, UDINT

{"value":1234}

0-4294967295

LTIME

8 byte unsigned, nanosecond duration, ULINT

{"value":12345}

0-18446744073709551615

DATE

Date, UDINT

{"value":"2020-03-12"}

(ISO 8601) "1990-01-01"-"2168-12-31"

LDATE

Date, ULINT

{"value":"2020-03-12"}

(ISO 8601) "1970-01-01"-"2554-07-21"

TIME_OF_DAY

Time of day milliseconds, UDINT

{"value":"01:23:45.678"}

(ISO 8601) "00:00:00.000"-"23:59:59.999"

LTIME_OF_DAY

Time of day nanoseconds, ULINT

{"value":"01:23:45.678901234"}

(ISO 8601) "00:00:00.000"-"23:59:59.999999999"

DATE_AND_TIME

DateTime milliseconds, UDINT

{"value":"2020-03-12"}

(ISO 8601) 1970-01-01T00:00:00.000-2089-12-31T23:59:59.999

LDATE_AND_TIME

DateTime nanoseconds, ULINT

{"value":"2020-03-12T23:59:59.123456789"}

(ISO 8601) 1970-01-01T00:00:00.000-2554-7-21-23:34:33.709551615

Table 31. Tag definition for ADS tags (definition)
Property Name Default Mandatory Description Format

tagAddress

The defined address of the tag

String

dataType

The data type

Selection of ADS data types

EtherNet/IP Logical Addressing Adapter

The EtherNet/IP Logical Addressing adapter connects HiveMQ Edge to any EtherNet/IP device that conforms to the Common Industrial Protocol (CIP). The adapter addresses data with numeric CIP logical paths in the format @class/instance/attribute. To read and write data, the adapter uses the generic CIP services Get_Attribute_Single and Set_Attribute_Single. Because logical addressing is part of the CIP standard, the adapter is vendor-neutral and is not limited to Rockwell or Allen-Bradley controllers.

This adapter uses CIP logical addressing (class/instance/attribute). The separate EtherNet/IP adapter (eip) uses Rockwell symbolic addressing (Controller Tag names). Select the Logical Addressing adapter when the CIP object model addresses the data on your device. Select the EtherNet/IP adapter for Rockwell ControlLogix/CompactLogix Controller Tags that you address by name. See Why HiveMQ Edge Provides Two EtherNet/IP Adapters.

Why HiveMQ Edge Provides Two EtherNet/IP Adapters

Symbolic addressing and logical addressing are two different ways to reach data over EtherNet/IP. Each method requires a different configuration model and different CIP services, so each method has a dedicated adapter.

  • Symbolic addressing is a Rockwell/Allen-Bradley extension of CIP. You address data with the Controller Tag that the program of the programmable logic controller (PLC) defines, for example Motor.Speed. The controller maintains a tag database that resolves each tag name and stores the data type of each tag. The tag database also describes structured tags (user-defined types, UDTs) with named members. Symbolic addressing is convenient and self-describing. However, symbolic addressing relies on the Rockwell tag database and is limited to Rockwell controllers such as ControlLogix and CompactLogix.

  • Logical addressing is the generic, vendor-neutral CIP mechanism that the ODVA specification defines. You address data by its position in the object model of the device with a numeric @class/instance/attribute path and read or write it with Get_Attribute_Single / Set_Attribute_Single. All CIP-conformant devices support logical addressing, not just Rockwell. The trade-off is that the device does not describe the data. For the client, an attribute is just a block of bytes. You must take the byte layout and the data types from the vendor documentation and configure the byte offsets and data types yourself. The batchByteIndex property, the dataType property, and the composite/batch model described below exist for this reason.

Because each addressing mode has its own configuration model, a dedicated adapter keeps each configuration clean and matched to your device. Most devices support a single addressing mode. Select the adapter that matches your device.

The adapter supports the following capabilities:

  • Read (Northbound): The adapter polls CIP attributes and publishes the resulting datapoints as MQTT messages on the configured topics.

  • Write (Southbound): The adapter writes values received as MQTT messages to CIP attributes.

  • Combine: Data combiners can use the datapoints the adapter publishes as inputs.

EtherNet/IP Logical Addressing Protocol ID

etheripCipOdva

Example minimal EtherNet/IP Logical Addressing adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-eip-odva-adapter</adapterId>
            <protocolId>etheripCipOdva</protocolId>
            <config>
                <host>my.eip-device.com</host>
                <byteOrder>LITTLE_ENDIAN</byteOrder>
                <eipToMqtt/>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <tagName>temperature</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>temperature</name>
                    <description>Reactor temperature</description>
                    <definition>
                        <address>@4/100/3</address>
                        <dataType>INT</dataType>
                        <readWrite>READ_ONLY</readWrite>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

EtherNet/IP Logical Addressing Adapter Properties (config)

Table 32. EtherNet/IP Logical Addressing Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

host

The host or IPv4/IPv6 address of the EtherNet/IP device.

Hostname or IP

slot

0

The controller slot to route to when the target is a CPU inside a chassis, for example a ControlLogix/CompactLogix rack reached by logical addressing. For a device that is itself the EtherNet/IP endpoint, keep the default value 0.

Integer

byteOrder

The byte order the adapter uses to decode and encode multi-byte numeric values: LITTLE_ENDIAN or BIG_ENDIAN.

Enum

eipToMqtt

The configuration for the EtherNet/IP to MQTT (Northbound) data flow.

eipToMqtt

The adapter uses the standard EtherNet/IP explicit-messaging port (TCP 44818). You cannot configure the port. There is no backplane setting; if you route to a CPU in a chassis, configure the target slot (the adapter uses the standard backplane port implicitly).

EtherNet/IP Logical Addressing Northbound config

Table 33. EtherNet/IP to MQTT (Northbound) (eipToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

The time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

The number of consecutive polling errors after which the adapter stops. Set to -1 to allow unlimited errors.

Integer >= -1

publishChangedDataOnly

true

When enabled, the adapter publishes a datapoint only when the value changes between polls. This reduces MQTT traffic for slow-changing data.

Boolean

EtherNet/IP Logical Addressing Tag Definition

A tag defines which CIP attribute to read or write and how to interpret its bytes.

Table 34. EtherNet/IP Logical Addressing Tag Definition Properties
Property Name Default Mandatory Description Format

address

The CIP logical address in the format @{class}/{instance}/{attribute}, for example @4/100/1. See EtherNet/IP Logical Addressing Tag Address for details.

String, matches @/[0-9]/[0-9]+

dataType

SINT

The CIP data type of the value, or COMPOSITE. See EtherNet/IP Logical Addressing Types for supported types.

Enum

numberOfElements

1

The number of elements to read. A value greater than 1 reads an array that starts at batchByteIndex.

Integer 1-1500

hysteresis

0

The minimum change that a value requires before the adapter republishes the value (dead-band). The adapter ignores the setting for boolean and string values.

Number

minUpdateIntervalMs

0

The interval in milliseconds after which the adapter republishes an unchanged value. The value 0 disables scheduled updates.

Integer

batchByteIndex

0

The 0-based byte offset of the tag within the attribute. The offset is required when several tags share one attribute and identifies the bytes that belong to the tag.

Integer

batchBitIndex

The bit index within a byte, for a BOOL tag. When the property is empty, the adapter checks whether the whole byte is not 0.

Integer 0-7

readWrite

READ_ONLY

The direction of the tag. READ_ONLY: the adapter polls the tag, no writes. WRITE_ONLY: southbound writes only, the adapter does not poll the tag. READ_WRITE: both directions.

Enum

writeMode

PARTIAL_WRITE

The way a write covers the attribute. See Writing (Southbound) for details.

Enum

EtherNet/IP Logical Addressing Tag Address

The general structure of tags is defined identically for each protocol adapter as described in Tags. The tag address for EtherNet/IP Logical Addressing is a CIP logical path that identifies a class, an instance, and an attribute in the object model of the device:

@\{class}/\{instance}/\{attribute}

For example, @4/100/1 addresses attribute 1 of instance 100 of class 4 (the Assembly object). The class, instance, and attribute numbers come from the documentation of the device vendor or from the Electronic Data Sheet (EDS) file of the device.

Device tag editor for the EtherNet/IP Logical Addressing adapter

Each tag carries its own @class/instance/attribute address and CIP data type, because a generic CIP device does not describe its own data.

Map Multiple Tags to One Attribute

A single CIP attribute often packs several fields into one block of bytes. The adapter reads or writes the whole attribute at once. To map individual fields to tags, use batchByteIndex and, for booleans, batchBitIndex. This mapping is the adapter equivalent of a structured attribute. You configure the byte offsets manually because a generic CIP device does not expose the structure and data type layout to the client.

The following example shows the whole model. The device defines the attribute @22/1/6 as an 8-byte attribute with the following layout.

Table 35. Attribute layout for @22/1/6 (device-defined, from the vendor documentation or the EDS file)
Byte offset Field CIP type

0

speed

UINT (2 bytes)

2

running

BOOL (bit 0 of byte 2)

3

mode

USINT (1 byte)

4-7

setpoint

REAL (4 bytes)

The following example defines three scalar tags for the relevant fields and one composite tag that aggregates them. The example intentionally omits the mode field.

Table 36. Tags defined for @22/1/6
Tag name dataType batchByteIndex batchBitIndex Note

speed

UINT

0

running

BOOL

2

0

setpoint

REAL

4

motor

COMPOSITE

0

Aggregates the three scalar tags above. Byte 3 (mode) is intentionally not mapped.

Composite Tags

A composite tag (dataType: COMPOSITE) aggregates the scalar tags configured at its address and direction into a single datapoint whose value is a JSON object with one key per tag name. Instead of publishing each field as its own message, the composite publishes one message:

{
  "value": { "speed": 1500, "running": true, "setpoint": 47.5 },
  "timestamp": 1756462706440,
  "tagName": "motor"
}

A composite tag requires at least one scalar sibling tag at the same address and direction. The adapter rejects a composite tag that lacks sibling tags at startup.

Writing (Southbound)

The adapter writes values received as MQTT messages to CIP attributes. A CIP attribute is the atomic write unit: one Set_Attribute_Single service call always replaces the entire attribute. The adapter offers two write modes that control how the supplied tags cover the attribute. The following descriptions reuse the @22/1/6 example.

Write mode Behavior

COMPLETE_WRITE

The adapter assumes that the configured tags at the address span the whole attribute and writes the attribute directly, without a read from the device. In the example, the tags cover bytes 0-2 and 4-7 but not byte 3 (mode). A COMPLETE_WRITE therefore produces a request that does not match the full width of the attribute, so the adapter cannot validate the coverage in advance. The rejection from the device at write time is the earliest reliable check. Use COMPLETE_WRITE only when your configured tags genuinely span the whole attribute.

PARTIAL_WRITE (default)

The configured tags cover only part of the attribute. The adapter preserves the rest of the attribute with a read-modify-write sequence. The adapter reads the current attribute from the device, overlays the supplied tag values, and writes the whole attribute back. In the example, PARTIAL_WRITE writes speed, running, and setpoint and leaves byte 3 (mode) and all other unmapped bytes unchanged.

Notes:

  • Set readWrite to WRITE_ONLY or READ_WRITE and add a southbound mapping to enable writing for a tag. WRITE_ONLY means the adapter does not poll or publish the tag northbound. WRITE_ONLY does not mean the device attribute is unreadable. You can use a WRITE_ONLY tag with PARTIAL_WRITE.

  • For a composite write, the message payload is a JSON object with one key per sibling tag name. The adapter writes all members of the composite tag.

  • The adapter strictly checks the type of every value. The adapter rejects a payload of the wrong JSON kind and a number outside the range of the CIP type. The adapter does not coerce or truncate values.

EtherNet/IP Logical Addressing Types

Type Description MQTT payload example Value range

BOOL

1 bit

{"value": true}

true/false

SINT

1-byte signed

{"value": -75}

-128 …​ 127

USINT

1-byte unsigned

{"value": 255}

0 …​ 255

INT

2-byte signed

{"value": -3450}

-32768 …​ 32767

UINT

2-byte unsigned

{"value": 3450}

0 …​ 65535

DINT

4-byte signed

{"value": -3450}

-2147483648 …​ 2147483647

UDINT

4-byte unsigned

{"value": 123232}

0 …​ 4294967295

LINT

8-byte signed

{"value": -123232000}

-9223372036854775808 …​ 9223372036854775807

REAL

4-byte floating point

{"value": 123.456789}

-3.4028235E38 …​ 3.4028235E38

LREAL

8-byte floating point

{"value": 123.456789}

-1.7976931348623157E308 …​ 1.7976931348623157E308

SSTRING

short string (1-byte length prefix)

{"value": "abc"}

ASCII

STRING

string (2-byte length prefix)

{"value": "abcdefgh"}

ASCII

COMPOSITE

aggregate of sibling tags at one address

{"value": {"a": 1, "b": true}}

object

ULINT (8-byte unsigned) is not currently supported, because its full range (0 to 264-1) does not fit a Java long. It may be added later.

EtherNet/IP Adapter

The EtherNet/IP adapter enables connections to Rockwell / Allen-Bradley PLCs (Programmable Logic Controllers) from the ControlLogix and CompactLogix series using the Ethernet/IP CIP protocol.

For a comparison of this adapter with the EtherNet/IP Logical Addressing adapter, and guidance on which to choose, see Why HiveMQ Edge Provides Two EtherNet/IP Adapters.

The adapter supports the following capability:

  • Read (Northbound): Poll EtherNet/IP tags and publish data to MQTT topics.

Example minimal EtherNet/IP adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-eip-protocol-adapter</adapterId>
            <protocolId>eip</protocolId>
            <config>
                <port>1234</port>
                <host>my.eip-server.com</host>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <tagName>tag-name</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag-name</name>
                    <description>description</description>
                    <definition>
                        <address>addressy</address>
                        <dataType>BOOL</dataType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>
Example full EtherNet/IP adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-eip-protocol-adapter</adapterId>
            <protocolId>eip</protocolId>
            <config>
                <host>my.eip-server.com</host>
                <port>1234</port>
                <backplane>4</backplane>
                <slot>5</slot>
                <eipToMqtt>
                    <pollingIntervalMillis>10</pollingIntervalMillis>
                    <maxPollingErrorsBeforeRemoval>9</maxPollingErrorsBeforeRemoval>
                    <publishChangedDataOnly>false</publishChangedDataOnly>
                </eipToMqtt>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <maxQos>1</maxQos>
                    <includeTagNames>true</includeTagNames>
                    <includeTimestamp>true</includeTimestamp>
                    <messageHandlingOptions>MQTTMessagePerSubscription</messageHandlingOptions>
                    <tagName>tag-name</tagName>
                    <mqttUserProperties>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value1</value>
                        </mqttUserProperty>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value2</value>
                        </mqttUserProperty>
                    </mqttUserProperties>
                </northboundMapping>
                <northboundMapping>
                    <topic>my/topic/2</topic>
                    <maxQos>1</maxQos>
                    <includeTagNames>true</includeTagNames>
                    <includeTimestamp>true</includeTimestamp>
                    <messageHandlingOptions>MQTTMessagePerSubscription</messageHandlingOptions>
                    <tagName>tag-name</tagName>
                    <mqttUserProperties>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value1</value>
                        </mqttUserProperty>
                        <mqttUserProperty>
                            <name>name</name>
                            <value>value2</value>
                        </mqttUserProperty>
                    </mqttUserProperties>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag-name</name>
                    <description>description</description>
                    <definition>
                        <address>addressy</address>
                        <dataType>BOOL</dataType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

EtherNet/IP Adapter Properties (config)

Table 37. EtherNet/IP Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

host

The host or IPv4/IPv6 of the EtherNet/IP device.

Hostname or IP

port

The TCP port to connect to (typical EtherNet/IP port is 44818).

Integer 1-65535

backplane

1

The backplane device value.

Integer

slot

0

The slot device value (specifies which CPU slot to target).

Integer

eipToMqtt

Configuration for EtherNet/IP to MQTT data flow

eipToMqtt

EtherNet/IP Northbound config

Table 38. EtherNet/IP to MQTT (Northbound) (eipToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries.

Integer >= -1

publishChangedDataOnly

true

When enabled, the adapter only publishes data when a value has changed since the last poll. This reduces MQTT traffic for slow-changing data.

Boolean

EtherNet/IP Tag Definition

Tags in the EtherNet/IP adapter define which Controller Tags to read.

Table 39. EtherNet/IP Tag Definition Properties
Property Name Default Mandatory Description Format

address

The Controller Tag name as shown in Logix/Studio 5000. See EtherNet/IP Tag Address for details.

String

dataType

The data type of the tag. See EtherNet/IP Types for supported types.

Enum

EtherNet/IP Tag Address

The general structure of tags is defined identically for each protocol adapter as described in Tags. The tag address for EtherNet/IP is the name of the Controller Tag as shown in Logix/Studio 5000.

040ff166 6984 4d38 881a 35e92ba969bd

Example: at_int_tag

EtherNet/IP Types

Type Description MQTT payload example Value range

BOOL

1 bit

{"value": true}

true/false

SINT

1 byte signed

{"value": -75}

-128-127

USINT

1 byte unsigned

{"value": 255}

0-255

INT

2 byte signed

{"value": -3450}

-32768-32767

UINT

2 byte unsigned

{"value": 3450}

0-65535

DINT

4 byte signed

{"value": -3450}

-2147483648-2147483647

UDINT

4 byte unsigned

{"value": 123232}

0-4294967295

LINT

8 byte signed

{"value": -123232000}

-9223372036854775808-9223372036854775807

ULINT

8 byte unsigned

{"value": 123232000}

0-18446744073709551615

REAL

4 byte floating point signed

{"value":123.456789} or {"value":3.4028235E38}

1.4E-45-3.4028235E38

LREAL

8 byte floating point signed

{"value":123.456789} or {"value":4.9E-324}

4.9E-324-1.7976931348623157E308

STRING

ascii string

{"value":"abcdefgh"}

ascii alphabet

TIME

4 byte unsigned, millisecond duration, UDINT

{"value":1234}

0-4294967295

LTIME

8 byte unsigned, nanosecond duration, ULINT

{"value":12345}

0-18446744073709551615

Table 40. Tag definition for EIP tags (definition)
Property Name Default Mandatory Description Format

tagAddress

The defined address of the tag

String

dataType

The data type

Selection of EIP data types

HTTP(s) Adapter

The HTTP adapter is useful when data points can be gathered via HTTP even when other IoT protocols are not available or other software systems should be integrated. The HTTP adapter polls data from a configurable endpoint and converts it into an MQTT message.

The adapter supports the following capabilities:

  • Read (Northbound): Poll HTTP endpoints and publish responses to MQTT topics.

The HTTP adapter does not have a publishChangedDataOnly option. Data is published on every polling interval regardless of whether it changed.
Example HTTP Protocol Adapter Configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-http-adapter</adapterId>
            <protocolId>http</protocolId>
            <config>
                <httpConnectTimeoutSeconds>5</httpConnectTimeoutSeconds>
                <httpToMqtt>
                    <pollingIntervalMillis>1000</pollingIntervalMillis>
                    <maxPollingErrorsBeforeRemoval>10</maxPollingErrorsBeforeRemoval>
                    <assertResponseIsJson>false</assertResponseIsJson>
                    <httpPublishSuccessStatusCodeOnly>true</httpPublishSuccessStatusCodeOnly>
                </httpToMqtt>
                <allowUntrustedCertificates>false</allowUntrustedCertificates>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <tagName>sensor-tag</tagName>
                    <topic>sensors/temperature</topic>
                    <maxQos>1</maxQos>
                    <messageExpiryInterval>9223372036854775807</messageExpiryInterval>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>sensor-tag</name>
                    <description>Temperature sensor HTTP endpoint</description>
                    <definition>
                        <url>http://sensor.local/api/temperature</url>
                        <httpRequestMethod>GET</httpRequestMethod>
                        <httpRequestTimeoutSeconds>5</httpRequestTimeoutSeconds>
                        <httpRequestBodyContentType>JSON</httpRequestBodyContentType>
                        <httpHeaders>
                            <httpHeader>
                                <name>Authorization</name>
                                <value>Bearer token123</value>
                            </httpHeader>
                        </httpHeaders>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

HTTP Adapter Properties (config)

Table 41. HTTP Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

id

The unique identifier of the protocol adapter.

String [a-zA-Z0-9-_]

httpConnectTimeoutSeconds

5

Timeout in seconds for HTTP connection establishment.

Integer (1-60)

allowUntrustedCertificates

false

Allow connections to untrusted SSL sources (expired certificates, self-signed, etc.).

Boolean

httpToMqtt

Configuration for HTTP to MQTT data flow

httpToMqtt

HTTP Northbound config

Table 42. HTTP to MQTT (Northbound) (httpToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Minimum value is 3.

Integer >= 3

httpPublishSuccessStatusCodeOnly

true

When enabled, only publish MQTT messages when the HTTP response code is successful (200-299).

Boolean

assertResponseIsJson

false

When enabled, forces parsing the HTTP response as JSON regardless of the Content-Type header.

Boolean

HTTP Tag Definition

Tags in the HTTP adapter define HTTP endpoints to poll or send data to.

Table 43. HTTP Tag Definition Properties
Property Name Default Mandatory Description Format

url

The URL of the HTTP endpoint.

URL

httpRequestMethod

GET

The HTTP method to use.

GET, POST, PUT

httpRequestTimeoutSeconds

5

Timeout in seconds for the HTTP request to complete.

Integer (1-60)

httpRequestBodyContentType

JSON

Content-Type for the request body.

JSON, PLAIN, HTML, XML, YAML

httpRequestBody

Request body content (required for POST/PUT methods).

String

httpHeaders

List of custom HTTP headers to include in requests.

List of HttpHeader

Table 44. HTTP Header Configuration
Property Name Default Mandatory Description Format

name

The name of the HTTP header.

String

value

The value of the HTTP header.

String

The adapter automatically adds a User-Agent: HiveMQ-Edge; <version> header to all requests.

File Adapter

The File adapter polls and publishes the content of files on a regular basis. The adapter supports different input formats and makes it possible to read information from systems that cannot communicate via the network or defined APIs.

The adapter supports the following capability:

  • Read (Northbound): Poll files from the local file system and publish content to MQTT topics.

The File adapter will ingest the whole content of the file (maximum 64KB per file). You can use HiveMQ Data Hub to extract specific information from the content of a file or transform a payload to fit your business needs.
The File adapter does not have a publishChangedDataOnly option. Files are polled and published on every interval regardless of whether the content has changed.

Example configuration to read a file from /tmp/sensor.json.

<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-file-protocol-adapter</adapterId>
            <protocolId>file</protocolId>
            <config>
                <fileToMqtt></fileToMqtt>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <tagName>tag1</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag1</name>
                    <description>decsription</description>
                    <definition>
                        <filePath>/tmp/sensor.json</filePath>
                        <contentType>TEXT_JSON</contentType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>

Example

Suppose a file named /tmp/sensor.json has the following example content:

{ "value": "42" }

Create the config as introduced above, the following MQTT payload is generated and shown below:

You can use any MQTT tool that is capable of showing an MQTT topic’s content. In the example, we use mqtt sub -t 'file-input'
{
  "timestamp" : 1730122091809,
  "value" : {
    "value" : "42"
  },
  "tagName" : "value",
  "contentType" : "application/json"
}

File Adapter Properties (config)

Table 45. File Protocol Adapter Properties (config)
Property Name Default Mandatory Description Format

id

The unique identifier of the protocol adapter.

String [a-zA-Z0-9-_]

fileToMqtt

Configuration for File to MQTT data flow

fileToMqtt

File Northbound config

Table 46. File to MQTT (Northbound) (fileToMqtt)
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between polling cycles.

Integer >= 1

maxPollingErrorsBeforeRemoval

10

Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries.

Integer >= -1

File Tag Definition

Tags in the File adapter define which files to poll.

Table 47. File Tag Definition Properties
Property Name Default Mandatory Description Format

filePath

The absolute path to the file to be read.

Path

contentType

The content type of the file.

See Content Types

File Content Types

Table 48. Supported File Content Types
Type MIME Type Description

BINARY

application/octet-stream

Binary data (Base64 encoded in MQTT payload)

TEXT_PLAIN

text/plain

Plain text content (UTF-8)

TEXT_JSON

application/json

JSON content (parsed into JSON tree)

TEXT_XML

application/xml

XML content (treated as plain text)

TEXT_CSV

text/csv

CSV content (treated as plain text)

Common Configurations

Table 49. List of Common Configurations for Northbound Mappings
Property Name Default Mandatory Description Format

topic

The topic to which the response is published.

MQTT topic

maxQos

0

MQTT Payload QoS

Integer (0-2)

includeTagNames

false

Include the name of the Tag in the payload.

Boolean

includeTimestamp

true

Add a timestamp to the MQTT payload.

Boolean

messageExpiryInterval

no expiry

The message expiry interval in seconds for MQTT 5 messages. Messages are removed from queues after this interval.

Long > 0

mqttUserProperties

List of mqttUserProperty defined over MQTT user properties for Protocol Adapters

publishChangedDataOnly

true

Specifies whether the adapter only publishes data when a field value change is detected. (Not available for all protocol adapters)

Boolean

MQTT User Properties for Protocol Adapters

MQTT User Properties can be added to each MQTT message created out of a Protocol Adapter payload. Any number of User Properties can be created. For more information of MQTT User Properties, read MQTT 5 User Properties.

Table 50. List of properties for MQTT User Properties for Protocol Adapters
Property Name Default Mandatory Description Format

name

Name of the Key of the MQTT User Property

String

value

Name of the Key of the MQTT User Property

String

BACnet Adapter

HiveMQ Edge supports the BACnet/IP protocol with the BACnet protocol adapter.

The adapter supports the following capability:

  • Read (Northbound): Poll BACnet objects and publish data to MQTT topics.

The BACnet adapter is not pre-packaged with HiveMQ Edge and must be installed separately.

Download and Install

The BACnet adapter file is available for download from the HiveMQ download server. You can replace the version number to the latest HiveMQ Edge version. The downloaded .jar file must be copied into the modules directory of your HiveMQ deployment Afterward, HiveMQ Edge must be restarted to use the protocol adapter.

Install in Docker

If you want to add the BACnet adapter to your Docker image, you can use the following snippet to get started:

ARG HIVEMQ_EDGE_VERSION
FROM hivemq/hivemq-edge:${HIVEMQ_EDGE_VERSION}

ARG HIVEMQ_EDGE_VERSION
ADD hivemq-edge-module-bacnetip-${HIVEMQ_EDGE_VERSION}-all.jar /opt/hivemq/modules/

The Dockerfile adds the pre-downloaded BACNet adapter to the HiveMQ Edge modules folder. To build the final image, enter the following command:

docker build --build-arg HIVEMQ_EDGE_VERSION=2025.2 -t my-custom-hivemq-edge .

The build argument HIVEMQ_EDGE_VERSION specifies the HiveMQ Edge version.

Configuration

Example minimal BACnet adapter configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <adapterId>my-bacnetip-protocol-adapter</adapterId>
            <protocolId>bacnet</protocolId>
            <config>
                <host>192.168.0.255</host>
                <port>47808</port>
                <deviceId>500</deviceId>
                <subnetBroadcastAddress>192.168.0.255</subnetBroadcastAddress>
                <discoveryIntervalMillis>10000</discoveryIntervalMillis>
                <bacnetipToMqtt>
                    <pollingIntervalMillis>10</pollingIntervalMillis>
                    <maxPollingErrorsBeforeRemoval>9</maxPollingErrorsBeforeRemoval>
                    <publishChangedDataOnly>false</publishChangedDataOnly>
                </bacnetipToMqtt>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>my/topic</topic>
                    <maxQos>1</maxQos>
                    <includeTimestamp>false</includeTimestamp>
                    <includeTagNames>true</includeTagNames>
                    <tagName>tag1</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag1</name>
                    <description>description1</description>
                    <definition>
                        <deviceInstanceNumber>1</deviceInstanceNumber>
                        <objectInstanceNumber>1</objectInstanceNumber>
                        <objectType>ANALOG_INPUT</objectType>
                        <propertyType>ACKED_TRANSITIONS</propertyType>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>
Table 51. General configuration
Property Name Default Mandatory Description Format

host

IP Address or hostname of the device to connect to

Hostname or IP

port

47808

The port number on the device to connect to

Port

deviceId

The device ID of the client used to obtain data via the BACnet/IP network

1-65535

subnetBroadcastAddress

The broadcast address of the BACnet/IP network

IP

discoveryIntervalMillis

5000

The time in milliseconds between checking the network for new devices

Milliseconds

bacnetipToMqtt

Object to define configuration of mappings from BACnet to MQTT

Object, BACnet to MQTT config

Table 52. BACnet to MQTT configuration
Property Name Default Mandatory Description Format

pollingIntervalMillis

1000

Time in milliseconds between pollings of this endpoint

Milliseconds

maxPollingErrorsBeforeRemoval

10

Maximum number of errors polling the endpoint before the polling daemon is stopped (-1 for unlimited retries)

Milliseconds

publishChangedDataOnly

true

Specifies whether the adapter only publishes data items that have changed since the last poll

true or false

Table 53. BACnet tag definition
Property Name Default Mandatory Description Format

deviceInstanceNumber

0

The instance number of the remote device on the network

Integer

objectInstanceNumber

0

The object number of the object on the remote device

Integer

objectType

The type of the object

ObjectType

propertyType

PRESENT_VALUE

The property of the object to fetch

PropertyType

Object Types

  • ANALOG_INPUT(0)

  • ANALOG_OUTPUT(1)

  • ANALOG_VALUE(2)

  • BINARY_INPUT(3)

  • BINARY_OUTPUT(4)

  • BINARY_VALUE(5)

  • CALENDAR(6)

  • COMMAND(7)

  • DEVICE(8)

  • EVENT_ENROLLMENT(9)

  • FILE(10)

  • GROUP(11)

  • LOOP(12)

  • MULTI_STATE_INPUT(13)

  • MULTI_STATE_OUTPUT(14)

  • NOTIFICATION_CLASS(15)

  • PROGRAM(16)

  • SCHEDULE(17)

  • AVERAGING(18)

  • MULTI_STATE_VALUE(19)

  • TREND_LOG(20)

  • LIFE_SAFETY_POINT(21)

  • LIFE_SAFETY_ZONE(22)

  • ACCUMULATOR(23)

  • PULSE_CONVERTER(24)

  • EVENT_LOG(25)

  • GLOBAL_GROUP(26)

  • TREND_LOG_MULTIPLE(27)

  • LOAD_CONTROL(28)

  • STRUCTURED_VIEW(29)

  • ACCESS_DOOR(30)

  • TIMER(31)

  • ACCESS_CREDENTIAL(32)

  • ACCESS_POINT(33)

  • ACCESS_RIGHTS(34)

  • ACCESS_USER(35)

  • ACCESS_ZONE(36)

  • CREDENTIAL_DATA_INPUT(37)

  • NETWORK_SECURITY(38)

  • BITSTRING_VALUE(39)

  • CHARACTERSTRING_VALUE(40)

  • DATE_PATTERN_VALUE(41)

  • DATE_VALUE(42)

  • DATETIME_PATTERN_VALUE(43)

  • DATETIME_VALUE(44)

  • INTEGER_VALUE(45)

  • LARGE_ANALOG_VALUE(46)

  • OCTETSTRING_VALUE(47)

  • POSITIVE_INTEGER_VALUE(48)

  • TIME_PATTERN_VALUE(49)

  • TIME_VALUE(50)

  • NOTIFICATION_FORWARDER(51)

  • ALERT_ENROLLMENT(52)

  • CHANNEL(53)

  • LIGHTING_OUTPUT(54)

  • BINARY_LIGHTING_OUTPUT(55)

  • NETWORK_PORT(56)

  • ELEVATOR_GROUP(57)

  • ESCALATOR(58)

  • LIFT(59)

Property Types

  • ACKED_TRANSITIONS(0)

  • ACK_REQUIRED(1)

  • ACTION(2)

  • ACTION_TEXT(3)

  • ACTIVE_TEXT(4)

  • ACTIVE_VT_SESSIONS(5)

  • ALARM_VALUE(6)

  • ALARM_VALUES(7)

  • ALL(8)

  • ALL_WRITES_SUCCESSFUL(9)

  • APDU_SEGMENT_TIMEOUT(10)

  • APDU_TIMEOUT(11)

  • APPLICATION_SOFTWARE_VERSION(12)

  • ARCHIVE(13)

  • BIAS(14)

  • CHANGE_OF_STATE_COUNT(15)

  • CHANGE_OF_STATE_TIME(16)

  • NOTIFICATION_CLASS(17)

  • CONTROLLED_VARIABLE_REFERENCE(19)

  • CONTROLLED_VARIABLE_UNITS(20)

  • CONTROLLED_VARIABLE_VALUE(21)

  • COV_INCREMENT(22)

  • DATE_LIST(23)

  • DAYLIGHT_SAVINGS_STATUS(24)

  • DEADBAND(25)

  • DERIVATIVE_CONSTANT(26)

  • DERIVATIVE_CONSTANT_UNITS(27)

  • DESCRIPTION(28)

  • DESCRIPTION_OF_HALT(29)

  • DEVICE_ADDRESS_BINDING(30)

  • DEVICE_TYPE(31)

  • EFFECTIVE_PERIOD(32)

  • ELAPSED_ACTIVE_TIME(33)

  • ERROR_LIMIT(34)

  • EVENT_ENABLE(35)

  • EVENT_STATE(36)

  • EVENT_TYPE(37)

  • EXCEPTION_SCHEDULE(38)

  • FAULT_VALUES(39)

  • FEEDBACK_VALUE(40)

  • FILE_ACCESS_METHOD(41)

  • FILE_SIZE(42)

  • FILE_TYPE(43)

  • FIRMWARE_REVISION(44)

  • HIGH_LIMIT(45)

  • INACTIVE_TEXT(46)

  • IN_PROCESS(47)

  • INSTANCE_OF(48)

  • INTEGRAL_CONSTANT(49)

  • INTEGRAL_CONSTANT_UNITS(50)

  • LIMIT_ENABLE(52)

  • LIST_OF_GROUP_MEMBERS(53)

  • LIST_OF_OBJECT_PROPERTY_REFERENCES(54)

  • LOCAL_DATE(56)

  • LOCAL_TIME(57)

  • LOCATION(58)

  • LOW_LIMIT(59)

  • MANIPULATED_VARIABLE_REFERENCE(60)

  • MAXIMUM_OUTPUT(61)

  • MAX_APDU_LENGTH_ACCEPTED(62)

  • MAX_INFO_FRAMES(63)

  • MAX_MASTER(64)

  • MAX_PRES_VALUE(65)

  • MINIMUM_OFF_TIME(66)

  • MINIMUM_ON_TIME(67)

  • MINIMUM_OUTPUT(68)

  • MIN_PRES_VALUE(69)

  • MODEL_NAME(70)

  • MODIFICATION_DATE(71)

  • NOTIFY_TYPE(72)

  • NUMBER_OF_APDU_RETRIES(73)

  • NUMBER_OF_STATES(74)

  • OBJECT_IDENTIFIER(75)

  • OBJECT_LIST(76)

  • OBJECT_NAME(77)

  • OBJECT_PROPERTY_REFERENCE(78)

  • OBJECT_TYPE(79)

  • OPTIONAL(80)

  • OUT_OF_SERVICE(81)

  • OUTPUT_UNITS(82)

  • EVENT_PARAMETERS(83)

  • POLARITY(84)

  • PRESENT_VALUE(85)

  • PRIORITY(86)

  • PRIORITY_ARRAY(87)

  • PRIORITY_FOR_WRITING(88)

  • PROCESS_IDENTIFIER(89)

  • PROGRAM_CHANGE(90)

  • PROGRAM_LOCATION(91)

  • PROGRAM_STATE(92)

  • PROPORTIONAL_CONSTANT(93)

  • PROPORTIONAL_CONSTANT_UNITS(94)

  • PROTOCOL_OBJECT_TYPES_SUPPORTED(96)

  • PROTOCOL_SERVICES_SUPPORTED(97)

  • PROTOCOL_VERSION(98)

  • READ_ONLY(99)

  • REASON_FOR_HALT(100)

  • RECIPIENT_LIST(102)

  • RELIABILITY(103)

  • RELINQUISH_DEFAULT(104)

  • REQUIRED(105)

  • RESOLUTION(106)

  • SEGMENTATION_SUPPORTED(107)

  • SETPOINT(108)

  • SETPOINT_REFERENCE(109)

  • STATE_TEXT(110)

  • STATUS_FLAGS(111)

  • SYSTEM_STATUS(112)

  • TIME_DELAY(113)

  • TIME_OF_ACTIVE_TIME_RESET(114)

  • TIME_OF_STATE_COUNT_RESET(115)

  • TIME_SYNCHRONIZATION_RECIPIENTS(116)

  • UNITS(117)

  • UPDATE_INTERVAL(118)

  • UTC_OFFSET(119)

  • VENDOR_IDENTIFIER(120)

  • VENDOR_NAME(121)

  • VT_CLASSES_SUPPORTED(122)

  • WEEKLY_SCHEDULE(123)

  • ATTEMPTED_SAMPLES(124)

  • AVERAGE_VALUE(125)

  • BUFFER_SIZE(126)

  • CLIENT_COV_INCREMENT(127)

  • COV_RESUBSCRIPTION_INTERVAL(128)

  • EVENT_TIME_STAMPS(130)

  • LOG_BUFFER(131)

  • LOG_DEVICE_OBJECT_PROPERTY(132)

  • ENABLE(133)

  • LOG_INTERVAL(134)

  • MAXIMUM_VALUE(135)

  • MINIMUM_VALUE(136)

  • NOTIFICATION_THRESHOLD(137)

  • PROTOCOL_REVISION(139)

  • RECORDS_SINCE_NOTIFICATION(140)

  • RECORD_COUNT(141)

  • START_TIME(142)

  • STOP_TIME(143)

  • STOP_WHEN_FULL(144)

  • TOTAL_RECORD_COUNT(145)

  • VALID_SAMPLES(146)

  • WINDOW_INTERVAL(147)

  • WINDOW_SAMPLES(148)

  • MAXIMUM_VALUE_TIMESTAMP(149)

  • MINIMUM_VALUE_TIMESTAMP(150)

  • VARIANCE_VALUE(151)

  • ACTIVE_COV_SUBSCRIPTIONS(152)

  • BACKUP_FAILURE_TIMEOUT(153)

  • CONFIGURATION_FILES(154)

  • DATABASE_REVISION(155)

  • DIRECT_READING(156)

  • LAST_RESTORE_TIME(157)

  • MAINTENANCE_REQUIRED(158)

  • MEMBER_OF(159)

  • MODE(160)

  • OPERATION_EXPECTED(161)

  • SETTING(162)

  • SILENCED(163)

  • TRACKING_VALUE(164)

  • ZONE_MEMBERS(165)

  • LIFE_SAFETY_ALARM_VALUES(166)

  • MAX_SEGMENTS_ACCEPTED(167)

  • PROFILE_NAME(168)

  • AUTO_SLAVE_DISCOVERY(169)

  • MANUAL_SLAVE_ADDRESS_BINDING(170)

  • SLAVE_ADDRESS_BINDING(171)

  • SLAVE_PROXY_ENABLE(172)

  • LAST_NOTIFY_RECORD(173)

  • SCHEDULE_DEFAULT(174)

  • ACCEPTED_MODES(175)

  • ADJUST_VALUE(176)

  • COUNT(177)

  • COUNT_BEFORE_CHANGE(178)

  • COUNT_CHANGE_TIME(179)

  • COV_PERIOD(180)

  • INPUT_REFERENCE(181)

  • LIMIT_MONITORING_INTERVAL(182)

  • LOGGING_OBJECT(183)

  • LOGGING_RECORD(184)

  • PRESCALE(185)

  • PULSE_RATE(186)

  • SCALE(187)

  • SCALE_FACTOR(188)

  • UPDATE_TIME(189)

  • VALUE_BEFORE_CHANGE(190)

  • VALUE_SET(191)

  • VALUE_CHANGE_TIME(192)

  • ALIGN_INTERVALS(193)

  • INTERVAL_OFFSET(195)

  • LAST_RESTART_REASON(196)

  • LOGGING_TYPE(197)

  • RESTART_NOTIFICATION_RECIPIENTS(202)

  • TIME_OF_DEVICE_RESTART(203)

  • TIME_SYNCHRONIZATION_INTERVAL(204)

  • TRIGGER(205)

  • UTC_TIME_SYNCHRONIZATION_RECIPIENTS(206)

  • NODE_SUBTYPE(207)

  • NODE_TYPE(208)

  • STRUCTURED_OBJECT_LIST(209)

  • SUBORDINATE_ANNOTATIONS(210)

  • SUBORDINATE_LIST(211)

  • ACTUAL_SHED_LEVEL(212)

  • DUTY_WINDOW(213)

  • EXPECTED_SHED_LEVEL(214)

  • FULL_DUTY_BASELINE(215)

  • REQUESTED_SHED_LEVEL(218)

  • SHED_DURATION(219)

  • SHED_LEVEL_DESCRIPTIONS(220)

  • SHED_LEVELS(221)

  • STATE_DESCRIPTION(222)

  • DOOR_ALARM_STATE(226)

  • DOOR_EXTENDED_PULSE_TIME(227)

  • DOOR_MEMBERS(228)

  • DOOR_OPEN_TOO_LONG_TIME(229)

  • DOOR_PULSE_TIME(230)

  • DOOR_STATUS(231)

  • DOOR_UNLOCK_DELAY_TIME(232)

  • LOCK_STATUS(233)

  • MASKED_ALARM_VALUES(234)

  • SECURED_STATUS(235)

  • ABSENTEE_LIMIT(244)

  • ACCESS_ALARM_EVENTS(245)

  • ACCESS_DOORS(246)

  • ACCESS_EVENT(247)

  • ACCESS_EVENT_AUTHENTICATION_FACTOR(248)

  • ACCESS_EVENT_CREDENTIAL(249)

  • ACCESS_EVENT_TIME(250)

  • ACCESS_TRANSACTION_EVENTS(251)

  • ACCOMPANIMENT(252)

  • ACCOMPANIMENT_TIME(253)

  • ACTIVATION_TIME(254)

  • ACTIVE_AUTHENTICATION_POLICY(255)

  • ASSIGNED_ACCESS_RIGHTS(256)

  • AUTHENTICATION_FACTORS(257)

  • AUTHENTICATION_POLICY_LIST(258)

  • AUTHENTICATION_POLICY_NAMES(259)

  • AUTHENTICATION_STATUS(260)

  • AUTHORIZATION_MODE(261)

  • BELONGS_TO(262)

  • CREDENTIAL_DISABLE(263)

  • CREDENTIAL_STATUS(264)

  • CREDENTIALS(265)

  • CREDENTIALS_IN_ZONE(266)

  • DAYS_REMAINING(267)

  • ENTRY_POINTS(268)

  • EXIT_POINTS(269)

  • EXPIRATION_TIME(270)

  • EXTENDED_TIME_ENABLE(271)

  • FAILED_ATTEMPT_EVENTS(272)

  • FAILED_ATTEMPTS(273)

  • FAILED_ATTEMPTS_TIME(274)

  • LAST_ACCESS_EVENT(275)

  • LAST_ACCESS_POINT(276)

  • LAST_CREDENTIAL_ADDED(277)

  • LAST_CREDENTIAL_ADDED_TIME(278)

  • LAST_CREDENTIAL_REMOVED(279)

  • LAST_CREDENTIAL_REMOVED_TIME(280)

  • LAST_USE_TIME(281)

  • LOCKOUT(282)

  • LOCKOUT_RELINQUISH_TIME(283)

  • MAX_FAILED_ATTEMPTS(285)

  • MEMBERS(286)

  • MUSTER_POINT(287)

  • NEGATIVE_ACCESS_RULES(288)

  • NUMBER_OF_AUTHENTICATION_POLICIES(289)

  • OCCUPANCY_COUNT(290)

  • OCCUPANCY_COUNT_ADJUST(291)

  • OCCUPANCY_COUNT_ENABLE(292)

  • OCCUPANCY_LOWER_LIMIT(294)

  • OCCUPANCY_LOWER_LIMIT_ENFORCED(295)

  • OCCUPANCY_STATE(296)

  • OCCUPANCY_UPPER_LIMIT(297)

  • OCCUPANCY_UPPER_LIMIT_ENFORCED(298)

  • PASSBACK_MODE(300)

  • PASSBACK_TIMEOUT(301)

  • POSITIVE_ACCESS_RULES(302)

  • REASON_FOR_DISABLE(303)

  • SUPPORTED_FORMATS(304)

  • SUPPORTED_FORMAT_CLASSES(305)

  • THREAT_AUTHORITY(306)

  • THREAT_LEVEL(307)

  • TRACE_FLAG(308)

  • TRANSACTION_NOTIFICATION_CLASS(309)

  • USER_EXTERNAL_IDENTIFIER(310)

  • USER_INFORMATION_REFERENCE(311)

  • USER_NAME(317)

  • USER_TYPE(318)

  • USES_REMAINING(319)

  • ZONE_FROM(320)

  • ZONE_TO(321)

  • ACCESS_EVENT_TAG(322)

  • GLOBAL_IDENTIFIER(323)

  • VERIFICATION_TIME(326)

  • BASE_DEVICE_SECURITY_POLICY(327)

  • DISTRIBUTION_KEY_REVISION(328)

  • DO_NOT_HIDE(329)

  • KEY_SETS(330)

  • LAST_KEY_SERVER(331)

  • NETWORK_ACCESS_SECURITY_POLICIES(332)

  • PACKET_REORDER_TIME(333)

  • SECURITY_PDU_TIMEOUT(334)

  • SECURITY_TIME_WINDOW(335)

  • SUPPORTED_SECURITY_ALGORITHMS(336)

  • UPDATE_KEY_SET_TIMEOUT(337)

  • BACKUP_AND_RESTORE_STATE(338)

  • BACKUP_PREPARATION_TIME(339)

  • RESTORE_COMPLETION_TIME(340)

  • RESTORE_PREPARATION_TIME(341)

  • BIT_MASK(342)

  • BIT_TEXT(343)

  • IS_UTC(344)

  • GROUP_MEMBERS(345)

  • GROUP_MEMBER_NAMES(346)

  • MEMBER_STATUS_FLAGS(347)

  • REQUESTED_UPDATE_INTERVAL(348)

  • COVU_PERIOD(349)

  • COVU_RECIPIENTS(350)

  • EVENT_MESSAGE_TEXTS(351)

  • EVENT_MESSAGE_TEXTS_CONFIG(352)

  • EVENT_DETECTION_ENABLE(353)

  • EVENT_ALGORITHM_INHIBIT(354)

  • EVENT_ALGORITHM_INHIBIT_REF(355)

  • TIME_DELAY_NORMAL(356)

  • RELIABILITY_EVALUATION_INHIBIT(357)

  • FAULT_PARAMETERS(358)

  • FAULT_TYPE(359)

  • LOCAL_FORWARDING_ONLY(360)

  • PROCESS_IDENTIFIER_FILTER(361)

  • SUBSCRIBED_RECIPIENTS(362)

  • PORT_FILTER(363)

  • AUTHORIZATION_EXEMPTIONS(364)

  • ALLOW_GROUP_DELAY_INHIBIT(365)

  • CHANNEL_NUMBER(366)

  • CONTROL_GROUPS(367)

  • EXECUTION_DELAY(368)

  • LAST_PRIORITY(369)

  • WRITE_STATUS(370)

  • PROPERTY_LIST(371)

  • SERIAL_NUMBER(372)

  • BLINK_WARN_ENABLE(373)

  • DEFAULT_FADE_TIME(374)

  • DEFAULT_RAMP_RATE(375)

  • DEFAULT_STEP_INCREMENT(376)

  • EGRESS_TIME(377)

  • IN_PROGRESS(378)

  • INSTANTANEOUS_POWER(379)

  • LIGHTING_COMMAND(380)

  • LIGHTING_COMMAND_DEFAULT_PRIORITY(381)

  • MAX_ACTUAL_VALUE(382)

  • MIN_ACTUAL_VALUE(383)

  • POWER(384)

  • TRANSITION(385)

  • EGRESS_ACTIVE(386)

  • INTERFACE_VALUE(387)

  • FAULT_HIGH_LIMIT(388)

  • FAULT_LOW_LIMIT(389)

  • LOW_DIFF_LIMIT(390)

  • STRIKE_COUNT(391)

  • TIME_OF_STRIKE_COUNT_RESET(392)

  • DEFAULT_TIMEOUT(393)

  • INITIAL_TIMEOUT(394)

  • LAST_STATE_CHANGE(395)

  • STATE_CHANGE_VALUES(396)

  • TIMER_RUNNING(397)

  • TIMER_STATE(398)

  • APDU_LENGTH(399)

  • IP_ADDRESS(400)

  • IP_DEFAULT_GATEWAY(401)

  • IP_DHCP_ENABLE(402)

  • IP_DHCP_LEASE_TIME(403)

  • IP_DHCP_LEASE_TIME_REMAINING(404)

  • IP_DHCP_SERVER(405)

  • IP_DNS_SERVER(406)

  • BACNET_IP_GLOBAL_ADDRESS(407)

  • BACNET_IP_MODE(408)

  • BACNET_IP_MULTICAST_ADDRESS(409)

  • BACNET_IP_NAT_TRAVERSAL(410)

  • IP_SUBNET_MASK(411)

  • BACNET_IP_UDP_PORT(412)

  • BBMD_ACCEPT_FD_REGISTRATIONS(413)

  • BBMD_BROADCAST_DISTRIBUTION_TABLE(414)

  • BBMD_FOREIGN_DEVICE_TABLE(415)

  • CHANGES_PENDING(416)

  • COMMAND(417)

  • FD_BBMD_ADDRESS(418)

  • FD_SUBSCRIPTION_LIFETIME(419)

  • LINK_SPEED(420)

  • LINK_SPEEDS(421)

  • LINK_SPEED_AUTONEGOTIATE(422)

  • MAC_ADDRESS(423)

  • NETWORK_INTERFACE_NAME(424)

  • NETWORK_NUMBER(425)

  • NETWORK_NUMBER_QUALITY(426)

  • NETWORK_TYPE(427)

  • ROUTING_TABLE(428)

  • VIRTUAL_MAC_ADDRESS_TABLE(429)

  • COMMAND_TIME_ARRAY(430)

  • CURRENT_COMMAND_PRIORITY(431)

  • LAST_COMMAND_TIME(432)

  • VALUE_SOURCE(433)

  • VALUE_SOURCE_ARRAY(434)

  • BACNET_IPV6_MODE(435)

  • IPV6_ADDRESS(436)

  • IPV6_PREFIX_LENGTH(437)

  • BACNET_IPV6_UDP_PORT(438)

  • IPV6_DEFAULT_GATEWAY(439)

  • BACNET_IPV6_MULTICAST_ADDRESS(440)

  • IPV6_DNS_SERVER(441)

  • IPV6_AUTO_ADDRESSING_ENABLE(442)

  • IPV6_DHCP_LEASE_TIME(443)

  • IPV6_DHCP_LEASE_TIME_REMAINING(444)

  • IPV6_DHCP_SERVER(445)

  • IPV6_ZONE_INDEX(446)

  • ASSIGNED_LANDING_CALLS(447)

  • CAR_ASSIGNED_DIRECTION(448)

  • CAR_DOOR_COMMAND(449)

  • CAR_DOOR_STATUS(450)

  • CAR_DOOR_TEXT(451)

  • CAR_DOOR_ZONE(452)

  • CAR_DRIVE_STATUS(453)

  • CAR_LOAD(454)

  • CAR_LOAD_UNITS(455)

  • CAR_MODE(456)

  • CAR_MOVING_DIRECTION(457)

  • CAR_POSITION(458)

  • ELEVATOR_GROUP(459)

  • ENERGY_METER(460)

  • ENERGY_METER_REF(461)

  • ESCALATOR_MODE(462)

  • FAULT_SIGNALS(463)

  • FLOOR_TEXT(464)

  • GROUP_ID(465)

  • GROUP_MODE(467)

  • HIGHER_DECK(468)

  • INSTALLATION_ID(469)

  • LANDING_CALLS(470)

  • LANDING_CALL_CONTROL(471)

  • LANDING_DOOR_STATUS(472)

  • LOWER_DECK(473)

  • MACHINE_ROOM_ID(474)

  • MAKING_CAR_CALL(475)

  • NEXT_STOPPING_FLOOR(476)

  • OPERATION_DIRECTION(477)

  • PASSENGER_ALARM(478)

  • POWER_MODE(479)

  • REGISTERED_CAR_CALL(480)

  • ACTIVE_COV_MULTIPLE_SUBSCRIPTIONS(481)

  • PROTOCOL_LEVEL(482)

  • REFERENCE_PORT(483)

  • DEPLOYED_PROFILE_LOCATION(484)

  • PROFILE_LOCATION(485)

  • TAGS(486)

  • SUBORDINATE_NODE_TYPES(487)

  • SUBORDINATE_TAGS(488)

  • SUBORDINATE_RELATIONSHIPS(489)

  • DEFAULT_SUBORDINATE_RELATIONSHIP(490)

  • REPRESENTS(491);

MTConnect Adapter

The MTConnect protocol adapter enables connections to MTConnect agents via HTTP/HTTPS.

The adapter supports the following capability:

  • Read (Northbound): Poll MTConnect agents and publish data to MQTT topics.

The MTConnect adapter does not have a publishChangedDataOnly option. Data is published on every polling interval regardless of whether it changed.

The MTConnect protocol adapter supports the following official MTConnect schemas and custom MTConnect schemas:

Schema Version

Assets

1.2 - 2.4

Devices

1.0 - 2.4

Error

1.1 - 2.4

Streams

1.1 - 2.4

Example MTConnect Protocol Adapter Configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <protocolId>mtconnect</protocolId>
            <adapterId>my-mtconnect-protocol-adapter</adapterId>
            <config>
                <id>my-mtconnect</id>
                <allowUntrustedCertificates>true</allowUntrustedCertificates>
                <pollingIntervalMillis>500</pollingIntervalMillis>
                <maxPollingErrorsBeforeRemoval>5</maxPollingErrorsBeforeRemoval>
            </config>
            <northboundMappings>
                <northboundMapping>
                    <topic>MTConnect/my-steams</topic>
                    <tagName>tag1</tagName>
                </northboundMapping>
            </northboundMappings>
            <tags>
                <tag>
                    <name>tag1</name>
                    <description>description1</description>
                    <definition>
                        <url>http://my-mtconnect.com</url>
                        <enableSchemaValidation>true</enableSchemaValidation>
                        <includeNull>false</includeNull>
                        <httpConnectTimeoutSeconds>5</httpConnectTimeoutSeconds>
                        <httpHeaders>
                            <httpHeader>
                                <name>header-name</name>
                                <value>header-value</value>
                            </httpHeader>
                        </httpHeaders>
                    </definition>
                </tag>
            </tags>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>
Table 54. Parameters for top-level configuration
Property Name Default Mandatory Description Format

allowUntrustedCertificates

false

Defines whether untrusted HTTP sources such as expired certificates can be accepted.

true, false

id

The unique identifier of the protocol adapter.

String

maxPollingErrorsBeforeRemoval

10

The number of times the adapter attempts to sample while an error condition is detected. If the configured maximum is exceeded, the sampling job ceases to execute until the connection is re-established.

Integer > 0

pollingIntervalMillis

1000

Time in milliseconds that the endpoint is polled.

Integer > 0

Table 55. Parameters for tag definition
Property Name Default Mandatory Description Format

enableSchemaValidation

false

Defines whether XML schema validation is performed. If your XML payloads conform to the official MTConnect schema, schema validation can help translate from the XML payload to a JSON payload more accurately. Otherwise, set schema validation to false.

true, false

httpConnectTimeoutSeconds

5

Defines the maximum time (in seconds) to wait for the underlying HTTP connection to be established.

Integer >= 1

httpHeaders

The HTTP headers in the requests to be sent to the MTConnect agent.

List

includeNull

false

Specifies whether fields with null values are included in the JSON payload.

true, false

url

Specifies the MTConnect agent endpoint the adapter polls. The MTConnect protocol adapter supports the MTConnect data types: Assets, Devices, Error, and Streams.

String

Table 56. Parameters for HTTP headers
Property Name Default Mandatory Description Format

name

The name of the HTTP header.

String

value

The value of the HTTP header.

String

Databases Adapter

The databases protocol adapter facilitates the integration of various database engines (PostgreSQL, MySQL, and MS SQL) with HiveMQ Edge.

The adapter supports the following capability:

  • Read (Northbound): Execute SQL queries and publish results to MQTT topics.

The Databases adapter does not have a publishChangedDataOnly option. Query results are published on every polling interval regardless of whether the data has changed.

Key Features

  • Supports PostgreSQL, MySQL, and MS SQL databases.

  • Supports one MQTT message per row in the result set (configurable via spiltLinesInIndividualMessages).

Example Databases Protocol Adapter Configuration
<hivemq>
    <protocol-adapters>
        <protocol-adapter>
            <protocolId>databases</protocolId>
            <adapterId>my-databases-protocol-adapter</adapterId>
            <configVersion>1</configVersion>
            <config>
                <type>MYSQL</type>
                <server>abc</server>
                <port>5432</port>
                <database>db</database>
                <username>root</username>
                <password>pass</password>
                <encrypt>true</encrypt>
                <trustCertificate>true</trustCertificate>
                <connectionTimeoutSeconds>30</connectionTimeoutSeconds>
                <pollingIntervalMillis>1000</pollingIntervalMillis>
                <maxPollingErrorsBeforeRemoval>10</maxPollingErrorsBeforeRemoval>
                <id>test</id>
            </config>
            <tags>
                <tag>
                    <name>test</name>
                    <description>test</description>
                    <definition>
                        <query>select * from test;</query>
                        <spiltLinesInIndividualMessages>true</spiltLinesInIndividualMessages>
                    </definition>
                </tag>
            </tags>
            <southboundMappings/>
            <northboundMappings>
                <northboundMapping>
                    <topic>test</topic>
                    <tagName>test</tagName>
                    <maxQos>0</maxQos>
                    <messageHandlingOptions>MQTTMessagePerTag</messageHandlingOptions>
                    <includeTagNames>false</includeTagNames>
                    <includeTimestamp>true</includeTimestamp>
                    <mqttUserProperties/>
                    <messageExpiryInterval>9223372036854775807</messageExpiryInterval>
                </northboundMapping>
            </northboundMappings>
        </protocol-adapter>
    </protocol-adapters>
</hivemq>
Table 57. Parameters for top-level configuration
Property Name Default Mandatory Description Format

id

The unique identifier of the protocol adapter.

String

type

The type of database to connect to.

POSTGRESQL, MYSQL or MSSQL

server

The hostname or IP address of the database server.

String

port

PostgreSQL: 5432, MySQL: 3306, MS SQL: 1433

The port number of the database server.

Integer 1 - 65535

database

The name of the database to connect to.

String

username

The username to connect to the database.

String

password

The password to connect to the database.

String

encrypt

false

Whether to use an encrypted connection to the database.

Boolean

trustCertificate

false

Whether to trust the server certificate when using an encrypted connection.

Boolean

connectionTimeoutSeconds

30

The maximum time in seconds to wait for the database connection to be established.

Integer > 0

maxPollingErrorsBeforeRemoval

10

The number of times the adapter attempts to sample while an error condition is detected. If the configured maximum is exceeded, the sampling job ceases to execute until the connection is re-established.

Integer > 0

pollingIntervalMillis

1000

Time in milliseconds that the endpoint is polled.

Integer > 0

Table 58. Parameters for tag definition
Property Name Default Mandatory Description Format

query

The SQL query to execute against the database. The query must return a result set.

String

spiltLinesInIndividualMessages

false

Whether to split the result set into individual messages. If set to true, each row in the result set is published as a separate MQTT message. If set to false, all lines are sent in a single message as an array.

Boolean

Contribute a Custom Adapter

The HiveMQ Edge protocol adapter SDK (Java Doc) can be utilized to implement a custom protocol adapter. For a step-by-step tutorial, see How to Build a File-based Protocol Adapter for HiveMQ Edge.