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:
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:
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.
-
northboundMappingsparameters
Property Name |
Default |
Mandatory |
Description |
Format |
tagName |
The tag name. |
String (Tags). For example, |
||
topic |
The MQTT topic. |
String. For example, |
||
maxQos |
1 |
The maximum MQTT QoS for the outgoing messages. |
Possible values are |
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The tag name |
String (Tags). For example, |
||
|
The MQTT topic filter to read from |
String. For example, |
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
tagNameandtimestamparound the tag’svalue, plusmetadataandcontextwhen the adapter supplies them. - Southbound (write)
-
The shape of what you may write to the device:
valuealone, with the rest of the envelope dropped.
// 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", "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
|
|
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 |
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.
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:

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

Once a topic filter is created, there are two ways to assign a schema:
-
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.

-
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.
|
{
"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.
{
"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.
All invalid messages are re-routed 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 capability:
-
Read (Northbound): Generate simulated data and publish to MQTT topics.
The example configuration publishes random data with MQTT quality of service level 1 to the destination topic called 'topic'.
<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
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The unique identifier of the selected adapter instance. |
String [a-zA-Z0-9-_] |
||
|
|
Minimum limit for the randomly generated values (inclusive). |
Integer >= 0 |
|
|
|
Maximum limit for the randomly generated values (exclusive). |
Integer |
|
|
|
Minimum artificial delay in milliseconds before the polling method generates a value. Must not exceed maxDelay. |
Integer >= 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 |
|
|
Configuration for polling and MQTT publishing |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. Each cycle generates new random values for all configured tags. |
Integer >= 1 |
|
|
|
Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries. |
Integer >= -1 |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
Common configurations |
{
"timestamp": 1730707250320,
"value": 729.6615064364747
}
The payload includes:
-
timestamp: Unix timestamp in milliseconds when the value was generated (only present ifincludeTimestampis true). -
value: Randomly generated double-precision floating-point number betweenminValue(inclusive) andmaxValue(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).
<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>
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
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The unique identifier of the selected adapter instance. |
String [a-zA-Z0-9-_] |
||
|
The host or IPv4/IPv6 of the ModBus device. |
Hostname or IP |
||
|
The port to connect to. |
Integer 1-65535 |
||
|
|
Time in milliseconds to await a connection before the client gives up. |
Integer (1000-15000) |
|
|
Configuration for Modbus to MQTT data flow |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries. |
Integer >= -1 |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The starting address index (inclusive) of the register to read. |
Integer (0-65535) |
||
|
Type of Modbus register to read. |
COILS, DISCRETE_INPUTS, INPUT_REGISTERS, HOLDING_REGISTERS |
||
|
Id of the unit (slave) to access on the Modbus network. |
Integer |
||
|
|
Defines how the read registers are interpreted. |
See Data Types |
|
|
|
When enabled, registers are evaluated in reverse order. Some Modbus implementations write content as big endian but order registers as little endian. |
Boolean |
ModBus Data Types
| Type | Description | Size |
|---|---|---|
|
Boolean value |
1 bit / 1 register |
|
Signed 16-bit integer |
16 bit / 1 register |
|
Unsigned 16-bit integer |
16 bit / 1 register |
|
Signed 32-bit integer |
32 bit / 2 registers |
|
Unsigned 32-bit integer |
32 bit / 2 registers |
|
Signed 64-bit integer |
64 bit / 4 registers |
|
32-bit floating-point (IEEE 754 single precision) |
32 bit / 2 registers |
|
64-bit floating-point (IEEE 754 double precision) |
64 bit / 4 registers |
|
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. |
<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. |
<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.
{
"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.
{
"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:
<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
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
URI of the OPC UA server to connect to |
URI (e.g., opc.tcp://server:4840) |
||
|
|
Override the endpoint URI returned from the OPC UA server with the hostname and port from the specified URI |
Boolean |
|
|
|
Overrides the |
String |
|
|
Authentication configuration for connecting to the OPC UA server |
Auth object OPC UA Authentication |
||
|
TLS configuration for secure connections |
TLS object Properties to configure TLS |
||
|
|
OPC UA Security Policy to use |
|
|
|
|
Message security mode. The default |
|
|
|
Configuration for OPC UA to MQTT (Northbound) data flow |
OpcUaToMqtt object OPC UA Northbound config details |
||
|
Connection handling options for heartbeats and reconnects |
ConnectionOptions object OPC UA Connection Options |
OPC UA Northbound config details
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
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 |
|
|
|
The number of data change notifications that the OPC UA server queues for each monitored item. Applies to |
Integer > 0 |
|
|
|
The number of event notifications that the OPC UA server queues for each event monitored item, which means |
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
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
OPC UA session timeout in milliseconds. Session will be renewed at this interval |
Integer (10000-3600000) |
|
|
|
Timeout for OPC UA requests in milliseconds |
Integer (5000-300000) |
|
|
|
Interval between OPC UA keep-alive pings in milliseconds |
Integer (1000-60000) |
|
|
|
Number of consecutive keep-alive failures before connection is considered dead |
Integer (1-10) |
|
|
|
Timeout for establishing connection to OPC UA server in milliseconds |
Integer (2000-300000) |
|
|
|
Interval between connection health checks in milliseconds |
Integer (10000-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"} |
|
|
|
Enable automatic reconnection when health check detects connection issues |
Boolean |
|
|
|
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.
<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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The OPC UA nodeId that identifies the data point on the server. For a |
OPC UA nodeId addressing schema |
||
|
|
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 |
|
|
|
|
For a |
The browse name of one of the 22 standard condition types, for example |
|
|
|
For a |
OPC UA nodeId addressing schema |
|
|
|
For an |
OPC UA nodeId addressing schema |
|
|
|
For an |
OPC UA nodeId addressing schema |
|
|
|
For an |
The browse name of one of the 22 standard condition types, for example |
|
Each remaining field is read by some kinds and ignored by the others: An empty or whitespace-only |
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:-
ifor numeric identifiers (e.g.,ns=1;i=1004) -
sfor string identifiers (e.g.,ns=1;s=Temperature) -
gfor GUID identifiers (e.g.,ns=1;g=550e8400-e29b-41d4-a716-446655440000) -
bfor opaque (ByteString) identifiers
-
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:
| kind | Purpose | Northbound | Southbound |
|---|---|---|---|
|
An ordinary variable (the default) |
The value |
The value |
|
One alarm |
Transition reports for that alarm |
Condition command |
|
A query against a notifier |
Transition reports from many alarms |
Not writable |
|
Trigger and observe condition refreshes |
Refresh control events |
Refresh command |
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.
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.
{
"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 samevalue/timestamp(andtagName, when the mapping asks for it) as any other tag. -
EventIdidentifies 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 thens=6;s=…string used in configuration. -
A two-state field is an object carrying the server’s display
textand the machine-readableid. Decide fromid:textis localized. -
A localized text such as
MessageorCommentis{"locale", "text"}, withlocaleabsent 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 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 |
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.
| What is wrong | What happens | Example message |
|---|---|---|
|
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 |
|
The adapter has more than one |
The adapter is created but fails to start, before any connection is opened |
|
The device disagrees with the tag |
That one tag is dropped and the adapter starts with the rest. A |
|
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
The same applies to a An unverified tag is an adapter event as well as a log line, so it appears in
|
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:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
<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.
| Method | Required arguments | comment |
Acts on |
|---|---|---|---|
|
|
Yes |
One transition |
|
|
Yes |
One transition |
|
|
Yes |
One transition |
|
|
Yes |
A dialog condition |
|
|
Yes |
Shelving state |
|
|
No |
The condition |
|
|
No |
The condition |
|
|
No |
The condition |
|
|
Yes |
The condition |
|
|
Yes |
The condition |
|
|
Yes |
The condition |
|
|
Yes |
The condition |
|
|
Yes |
The condition |
|
|
Yes |
Shelving state |
|
|
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"}
| Field | Type | Meaning |
|---|---|---|
|
String |
Which method to invoke, named as in the table above. Always required, matched case-insensitively |
|
String |
The |
|
String |
Free text the server records alongside the transition |
|
Number |
Shelving time in milliseconds. Required for |
|
Integer |
Zero-based index into the dialog’s |
|
|
|
Never send a command field as an explicit This matters for a caller that builds the command as an object and then serializes it.
Jackson, |
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:
| Event | What it means |
|---|---|
|
The server has begun re-reporting its retained conditions |
|
It has finished. Everything between the two is the current picture, not new transitions |
|
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 |
|
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.
{"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
This matters because an event is a transition report and is never re-sent. Neither a reconnect nor a
|
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.
<opcua>
<config>
<uri>opc.tcp://opcua-server:4840</uri>
<!-- No auth block = anonymous authentication -->
</config>
</opcua>
OPC UA Basic Authentication
<opcua>
<config>
...
<auth>
<basic>
<username>edge</username>
<password>password</password>
</basic>
</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.
|
<opcua>
<config>
...
<tls>
<enabled>true</enabled>
</tls>
...
</config>
</opcua>
<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.
<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>
| Property Name | Default | Mandatory | Description |
|---|---|---|---|
|
|
Enables TLS encrypted connection |
|
|
|
Named certificate-validation preset. See the presets. Mutually exclusive with |
|
|
The six individual validation axes, for cases the presets do not cover. See Individual validation axes. Mutually exclusive with |
||
|
Keystore configuration containing the client certificate including the chain. Required whenever the security policy is not |
||
|
Path on the local file system to the keystore |
||
|
Password to open the keystore |
||
|
Password to access the private key |
||
|
|
Truststore configuration containing trusted server certificates or trusted intermediates |
|
|
Path on the local file system to the truststore |
||
|
Password to open the truststore |
||
|
Allow list of permitted server-certificate fingerprints. See Trusting self-signed certificates by fingerprint. Required when the effective trust mode is |
||
|
Path on the local file system to the fingerprint allow list |
||
|
Certificate revocation lists used by |
||
|
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:
-
tlsChecksis a named preset. One value covers the common cases. -
tlsChecksFullholds 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. |
| Value | Description |
|---|---|
|
(Default.) The certificate must chain to a trust anchor, carry the expected OPC UA |
|
As |
|
The certificate must chain to a trust anchor and carry the expected |
|
The certificate must chain to a trust anchor. Nothing else is checked. Note that this does not mean "no validation". See the warning below. |
|
For environments with no CA. The certificate’s fingerprint must appear in the configured allow list, and it must carry the expected |
|
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 |
|---|---|---|---|
|
|
|
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. |
|
|
|
Whether the |
|
|
|
Whether the endpoint hostname must match a SubjectAltName DNS name or IP address in the certificate. |
|
|
|
Whether the certificate’s validity period is enforced. |
|
|
|
How hard revocation status is enforced: |
|
|
|
How strictly the certificate’s declared purpose is enforced: |
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.
|
| Preset | trustMode | sanUri | hostname | validity | revocation | keyUsage |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
| Environment | Setting |
|---|---|
Server certificate placed in the truststore, so that it is its own trust anchor |
|
The same, where the certificate also names its host and declares server-authentication key usage |
|
Any chain with an issuing CA, whether public CA, corporate PKI or private CA |
|
The same, where the CA publishes no CRLs at all |
|
Self-signed per-device certificates, no CA |
|
Self-signed certificates that carry no hostname |
|
No verification possible or wanted, MITM risk accepted |
|
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
Because 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:
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
Where a CA genuinely publishes no CRLs, set |
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 |
|---|---|
|
No endpoint offered by the server matches the configured security policy and message security mode. Most often a secured |
|
The server certificate does not chain to anything in the truststore, or in the JVM |
|
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. |
|
The endpoint hostname does not appear in the certificate. Either correct the endpoint URI, or drop the check with |
|
The |
|
The certificate lacks the KeyUsage or ExtendedKeyUsage extensions the configuration demands. Device certificates frequently omit these. |
|
The certificate is expired or not yet valid. Replace it, or relax |
|
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 |
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 -sha256Both 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.
<opcua>
<config>
...
<security>
<policy>BASIC128RSA15</policy>
<messageSecurityMode>SIGN_AND_ENCRYPT</messageSecurityMode>
</security>
...
</config>
</opcua>
| Property Name | Default | Mandatory | Values | Description |
|---|---|---|---|---|
|
|
|
General security policy used for message exchange |
|
|
|
|
Message security mode used for message exchange. The default |
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:
| JSON Type | Description | OPC UA Types |
|---|---|---|
|
Boolean values (true/false) |
Boolean |
|
Integer numeric values |
Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64 |
|
Floating-point numeric values |
Float, Double |
|
Text values |
String, LocalizedText, ByteString |
|
Date and time values (ISO 8601 format) |
DateTime |
|
Arrays of the above types |
Arrays of any supported type |
|
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.
|
<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)
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The host or IPv4/IPv6 of the S7 device. |
Hostname or IP |
||
|
|
The port to which the adapter connects. |
Integer 1-65535 |
|
|
|
The series of the S7 PLC. |
|
|
|
|
Rack value for the remote main CPU. |
Integer |
|
|
|
Slot value for the remote main CPU. |
Integer |
|
|
|
Rack value for the remote secondary CPU. |
Integer |
|
|
|
Slot value for the remote secondary CPU. |
Integer |
|
|
|
Remote TSAP (Transport Services Access Point) value. Usually required only for PLCs from the LOGO series. |
Integer |
|
|
|
Enable keep-alive ping to prevent TCP timeouts. Recommended when polling interval exceeds 7 seconds. Automatically enabled if polling interval is >= 7000ms. |
Boolean |
|
|
Configuration for S7 to MQTT data flow |
S7 Northbound config
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries. |
Integer >= -1 |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The address of the S7 tag to read. See S7 Tag Address for format. |
String |
||
|
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.
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
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.
S7 Types
| Type | Description | Memory size code | MQTT payload example | Value range |
|---|---|---|---|---|
|
1 bit |
|
|
|
|
1 byte unsigned |
|
|
|
|
1 byte signed |
|
|
|
|
1 byte unsigned |
|
|
|
|
2 byte signed |
|
|
|
|
2 byte unsigned |
|
|
|
|
4 byte signed |
|
|
|
|
4 byte unsigned |
|
|
|
|
8 byte signed |
|
|
|
|
8 byte unsigned |
|
|
|
|
2 byte unsigned |
|
|
|
|
4 byte unsigned |
|
|
|
|
8 byte unsigned |
|
|
|
|
4 byte floating point signed |
|
|
|
|
8 byte floating point signed |
|
|
|
|
1 byte character |
|
|
ascii alphabet |
|
2 byte character |
|
|
unicode alphabet |
|
ascii string |
|
|
ascii alphabet |
|
unicode string |
|
|
unicode alphabet |
|
4 byte signed, millisecond duration |
|
|
|
|
8 byte signed, nanosecond duration |
|
|
|
|
Date |
|
|
(ISO 8601) |
|
Time of day milliseconds |
|
|
(ISO 8601) |
|
Time of day nanoseconds |
|
|
(ISO 8601) |
|
DateTime milliseconds |
|
|
(ISO 8601) |
|
DateTime nanoseconds |
|
|
(ISO 8601) |
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.
<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>
<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)
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The host or IPv4/IPv6 of the ADS device. |
Hostname or IP |
||
|
|
The TCP port to connect to. |
Integer 1-65535 |
|
|
The AMS Net ID of the device to connect to (6 octets). |
String (e.g., |
||
|
|
The AMS port number on the device to connect to. Typical TwinCAT runtime port is 851. |
Integer 1-65535 |
|
|
The AMS Net ID used by HiveMQ Edge (6 octets). |
String (e.g., |
||
|
|
The local AMS port number used by HiveMQ Edge. |
Integer 1-65535 |
|
|
|
Enable TCP keep-alive to maintain connection during inactivity. |
Boolean |
|
|
Configuration for ADS to MQTT data flow |
ADS Northbound config
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries. |
Integer >= -1 |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The ADS address of the variable to read. See ADS Tag Address for format. |
String |
||
|
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 |
|---|---|---|---|
|
1 bit |
|
|
|
1 byte unsigned |
|
|
|
1 byte signed |
|
|
|
1 byte unsigned |
|
|
|
2 byte signed |
|
|
|
2 byte unsigned |
|
|
|
4 byte signed |
|
|
|
4 byte unsigned |
|
|
|
8 byte signed |
|
|
|
8 byte unsigned |
|
|
|
2 byte unsigned |
|
|
|
4 byte unsigned |
|
|
|
8 byte unsigned |
|
|
|
4 byte floating point signed |
|
|
|
8 byte floating point signed |
|
|
|
ascii string |
|
|
|
unicode string |
|
|
|
4 byte unsigned, millisecond duration, UDINT |
|
|
|
8 byte unsigned, nanosecond duration, ULINT |
|
|
|
Date, UDINT |
|
|
|
Date, ULINT |
|
|
|
Time of day milliseconds, UDINT |
|
|
|
Time of day nanoseconds, ULINT |
|
|
|
DateTime milliseconds, UDINT |
|
|
|
DateTime nanoseconds, ULINT |
|
|
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The defined address of the tag |
String |
||
|
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 ( |
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/attributepath and read or write it withGet_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. ThebatchByteIndexproperty, thedataTypeproperty, 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
<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)
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The host or IPv4/IPv6 address of the EtherNet/IP device. |
Hostname or IP |
||
|
|
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 |
|
|
The byte order the adapter uses to decode and encode multi-byte numeric values: |
Enum |
||
|
The configuration for the EtherNet/IP to MQTT (Northbound) data flow. |
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
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
The time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
The number of consecutive polling errors after which the adapter stops. Set to -1 to allow unlimited errors. |
Integer >= -1 |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The CIP logical address in the format |
String, matches |
||
|
|
The CIP data type of the value, or |
Enum |
|
|
|
The number of elements to read. A value greater than 1 reads an array that starts at |
Integer 1-1500 |
|
|
|
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 |
|
|
|
The interval in milliseconds after which the adapter republishes an unchanged value. The value 0 disables scheduled updates. |
Integer |
|
|
|
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 |
|
|
The bit index within a byte, for a |
Integer 0-7 |
||
|
|
The direction of the tag. |
Enum |
|
|
|
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.
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.
| Byte offset | Field | CIP type |
|---|---|---|
|
speed |
|
|
running |
|
|
mode |
|
|
setpoint |
|
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.
| Tag name | dataType | batchByteIndex | batchBitIndex | Note |
|---|---|---|---|---|
|
|
0 |
||
|
|
2 |
0 |
|
|
|
4 |
||
|
|
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 |
|---|---|
|
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 ( |
|
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, |
Notes:
-
Set
readWritetoWRITE_ONLYorREAD_WRITEand add a southbound mapping to enable writing for a tag.WRITE_ONLYmeans the adapter does not poll or publish the tag northbound.WRITE_ONLYdoes not mean the device attribute is unreadable. You can use aWRITE_ONLYtag withPARTIAL_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 |
|---|---|---|---|
|
1 bit |
|
|
|
1-byte signed |
|
|
|
1-byte unsigned |
|
|
|
2-byte signed |
|
|
|
2-byte unsigned |
|
|
|
4-byte signed |
|
|
|
4-byte unsigned |
|
|
|
8-byte signed |
|
|
|
4-byte floating point |
|
|
|
8-byte floating point |
|
|
|
short string (1-byte length prefix) |
|
|
|
string (2-byte length prefix) |
|
|
|
aggregate of sibling tags at one address |
|
|
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.
<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>
<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)
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The host or IPv4/IPv6 of the EtherNet/IP device. |
Hostname or IP |
||
|
The TCP port to connect to (typical EtherNet/IP port is 44818). |
Integer 1-65535 |
||
|
|
The backplane device value. |
Integer |
|
|
|
The slot device value (specifies which CPU slot to target). |
Integer |
|
|
Configuration for EtherNet/IP to MQTT data flow |
EtherNet/IP Northbound config
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
Maximum number of consecutive polling errors before the adapter stops. Set to -1 for unlimited retries. |
Integer >= -1 |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The Controller Tag name as shown in Logix/Studio 5000. See EtherNet/IP Tag Address for details. |
String |
||
|
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.
Example: at_int_tag
EtherNet/IP Types
| Type | Description | MQTT payload example | Value range |
|---|---|---|---|
|
1 bit |
|
|
|
1 byte signed |
|
|
|
1 byte unsigned |
|
|
|
2 byte signed |
|
|
|
2 byte unsigned |
|
|
|
4 byte signed |
|
|
|
4 byte unsigned |
|
|
|
8 byte signed |
|
|
|
8 byte unsigned |
|
|
|
4 byte floating point signed |
|
|
|
8 byte floating point signed |
|
|
|
ascii string |
|
|
|
4 byte unsigned, millisecond duration, UDINT |
|
|
|
8 byte unsigned, nanosecond duration, ULINT |
|
|
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The defined address of the tag |
String |
||
|
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.
|
<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)
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The unique identifier of the protocol adapter. |
String [a-zA-Z0-9-_] |
||
|
|
Timeout in seconds for HTTP connection establishment. |
Integer (1-60) |
|
|
|
Allow connections to untrusted SSL sources (expired certificates, self-signed, etc.). |
Boolean |
|
|
Configuration for HTTP to MQTT data flow |
HTTP Northbound config
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
Maximum number of consecutive polling errors before the adapter stops. Minimum value is 3. |
Integer >= 3 |
|
|
|
When enabled, only publish MQTT messages when the HTTP response code is successful (200-299). |
Boolean |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The URL of the HTTP endpoint. |
URL |
||
|
|
The HTTP method to use. |
|
|
|
|
Timeout in seconds for the HTTP request to complete. |
Integer (1-60) |
|
|
|
Content-Type for the request body. |
|
|
|
Request body content (required for POST/PUT methods). |
String |
||
|
List of custom HTTP headers to include in requests. |
List of HttpHeader |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The name of the HTTP header. |
String |
||
|
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)
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The unique identifier of the protocol adapter. |
String [a-zA-Z0-9-_] |
||
|
Configuration for File to MQTT data flow |
File Northbound config
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between polling cycles. |
Integer >= 1 |
|
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The absolute path to the file to be read. |
Path |
||
|
The content type of the file. |
See Content Types |
File Content Types
| Type | MIME Type | Description |
|---|---|---|
|
application/octet-stream |
Binary data (Base64 encoded in MQTT payload) |
|
text/plain |
Plain text content (UTF-8) |
|
application/json |
JSON content (parsed into JSON tree) |
|
application/xml |
XML content (treated as plain text) |
|
text/csv |
CSV content (treated as plain text) |
Common Configurations
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The topic to which the response is published. |
MQTT topic |
||
|
|
MQTT Payload QoS |
Integer (0-2) |
|
|
|
Include the name of the Tag in the payload. |
Boolean |
|
|
|
Add a timestamp to the MQTT payload. |
Boolean |
|
|
|
The message expiry interval in seconds for MQTT 5 messages. Messages are removed from queues after this interval. |
Long > 0 |
|
|
List of |
|||
|
|
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.
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
Name of the Key of the MQTT User Property |
String |
||
|
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
<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>
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
IP Address or hostname of the device to connect to |
Hostname or IP |
||
|
|
The port number on the device to connect to |
Port |
|
|
The device ID of the client used to obtain data via the BACnet/IP network |
1-65535 |
||
|
The broadcast address of the BACnet/IP network |
IP |
||
|
|
The time in milliseconds between checking the network for new devices |
Milliseconds |
|
|
Object to define configuration of mappings from BACnet to MQTT |
Object, BACnet to MQTT config |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Time in milliseconds between pollings of this endpoint |
Milliseconds |
|
|
|
Maximum number of errors polling the endpoint before the polling daemon is stopped (-1 for unlimited retries) |
Milliseconds |
|
|
|
Specifies whether the adapter only publishes data items that have changed since the last poll |
|
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
The instance number of the remote device on the network |
Integer |
|
|
|
The object number of the object on the remote device |
Integer |
|
|
The type of the object |
|||
|
|
The property of the object to fetch |
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 |
<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>
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
Defines whether untrusted HTTP sources such as expired certificates can be accepted. |
|
|
|
The unique identifier of the protocol adapter. |
String |
||
|
|
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 |
|
|
|
Time in milliseconds that the endpoint is polled. |
Integer > 0 |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
|
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 |
|
|
|
|
Defines the maximum time (in seconds) to wait for the underlying HTTP connection to be established. |
Integer >= 1 |
|
|
The HTTP headers in the requests to be sent to the MTConnect agent. |
List |
||
|
|
Specifies whether fields with null values are included in the JSON payload. |
|
|
|
Specifies the MTConnect agent endpoint the adapter polls. The MTConnect protocol adapter supports the MTConnect data types: Assets, Devices, Error, and Streams. |
String |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The name of the HTTP header. |
String |
||
|
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).
<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>
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The unique identifier of the protocol adapter. |
String |
||
|
The type of database to connect to. |
POSTGRESQL, MYSQL or MSSQL |
||
|
The hostname or IP address of the database server. |
String |
||
|
|
The port number of the database server. |
Integer 1 - 65535 |
|
|
The name of the database to connect to. |
String |
||
|
The username to connect to the database. |
String |
||
|
The password to connect to the database. |
String |
||
|
|
Whether to use an encrypted connection to the database. |
Boolean |
|
|
|
Whether to trust the server certificate when using an encrypted connection. |
Boolean |
|
|
|
The maximum time in seconds to wait for the database connection to be established. |
Integer > 0 |
|
|
|
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 |
|
|
|
Time in milliseconds that the endpoint is polled. |
Integer > 0 |
| Property Name | Default | Mandatory | Description | Format |
|---|---|---|---|---|
|
The SQL query to execute against the database. The query must return a result set. |
String |
||
|
|
Whether to split the result set into individual messages. If set to |
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.