Integrating MQTT Topics with AMPS
This page assumes a bridge, adapter, or application republishes MQTT messages into AMPS while preserving the original MQTT topic in the AMPS topic name or in a message field. That approach preserves familiar MQTT topic hierarchies while using AMPS as the queryable, stateful layer for dashboards, operational tooling, and interactive applications. The same conventions also keep a straightforward path for applications that later publish directly into AMPS.
Where MQTT and AMPS Overlap
MQTT and AMPS both rely on hierarchical topic names. AMPS can preserve MQTT wildcard patterns by using TopicMatchingPolicy set to mqtt as the instance default or as a local override on the imported MQTT namespace. Subscriptions and SOW queries can also use topic_matching_policy=mqtt, and any TOPIC_MATCH predicate in the same command filter uses MQTT wildcard rules.
That overlap is useful when a team wants to preserve MQTT topic trees such as sensors/device1/temperature or factory/line3/alarms while adding:
- Persistent current state through the State of the World (SOW)
- Atomic initial load plus live updates through
sow_and_subscribe - Lower-bandwidth browser updates through
sow_and_delta_subscribe - Server-managed rollups with Views and Unions
- UI-friendly refresh rates with ConflatedTopics
MQTT Patterns Compared to Default AMPS PCRE
The default AMPS topic matching policy is pcre, which uses full regular expressions. MQTT syntax is simpler and maps directly to MQTT topic semantics.
| MQTT Pattern | Meaning | Representative PCRE Equivalent |
|---|---|---|
sensors/+/temperature | Match exactly one level between sensors and temperature, including an empty level | ^sensors/[^/]*/temperature$ |
sensors/# | Match sensors and everything below it | ^sensors(/.*)?$ |
# | Match every non-system topic | ^(?![$]).*$ |
Under mqtt, + matches exactly one topic level, which can be empty, and # matches zero or more trailing topic levels. Following MQTT rules, filters that begin with + or # do not match topic names that begin with $. Constructs such as ^, $, and .* are PCRE syntax, not MQTT syntax.
Recommended AMPS Design
For most MQTT integrations, the cleanest AMPS design looks like this:
- Preserve the original MQTT topic when the bridge publishes into AMPS.
- Keep the instance default at
pcreunless most of the instance uses MQTT semantics. For imported MQTT namespaces, addTopicMatchingPolicyset tomqttbeside eachPatternorUnderlyingTopicthat should use MQTT rules. - Capture the relevant topic space into a Pattern topic so AMPS maintains current state per logical MQTT topic without a separate SOW topic definition for each topic.
- Build a Union whose
UnderlyingTopicrepeats that same pattern expression when dashboards or downstream services need one consolidated SOW topic. - Build Views and ConflatedTopics on top of that union for operator dashboards and UI refresh.
This layout works well for phased coexistence and for direct AMPS adoption later because the topic model presented to applications stays stable.
A Pattern topic cannot be used directly as the underlying source for a View. Use a Union first, with the same pattern expression in the Union UnderlyingTopic, then place the View or ConflatedTopic on top of the Union.
Sample Configuration
The following example keeps the instance default at pcre, preserves an MQTT sensor namespace inside AMPS with local MQTT overrides, rolls it into a single SOW topic for analytics, and then produces a dashboard-oriented topic:
<AMPSConfig>
<Name>mqtt-observability</Name>
<TopicMatchingPolicy>pcre</TopicMatchingPolicy>
<SOW>
<Topic>
<Name>mqtt-sensor-space</Name>
<Pattern>sensors/#</Pattern>
<TopicMatchingPolicy>mqtt</TopicMatchingPolicy>
<MessageType>json</MessageType>
<Key>/sensorId</Key>
<FileName>./sow/%n.sow</FileName>
</Topic>
<Union>
<Name>mqtt-sensor-union</Name>
<MessageType>json</MessageType>
<UnderlyingTopic>sensors/#</UnderlyingTopic>
<TopicMatchingPolicy>mqtt</TopicMatchingPolicy>
</Union>
<View>
<Name>mqtt-sensors-by-site</Name>
<MessageType>json</MessageType>
<UnderlyingTopic>mqtt-sensor-union</UnderlyingTopic>
<Projection>
<Field>/site</Field>
<Field>COUNT(/sensorId) AS /sensorCount</Field>
</Projection>
<Grouping>
<Field>/site</Field>
</Grouping>
</View>
<ConflatedTopic>
<Name>mqtt-sensors-by-site-ui</Name>
<MessageType>json</MessageType>
<UnderlyingTopic>mqtt-sensors-by-site</UnderlyingTopic>
<Interval>1s</Interval>
</ConflatedTopic>
</SOW>
</AMPSConfig>
If you truly want to capture the entire MQTT topic namespace, use # as the Pattern. In practice, most teams use a bounded namespace such as sensors/# or factory/# so entitlements, monitoring, and disk planning stay predictable.
Usage Tips
- Use
TOPIC_MATCHwhen a field stores the original MQTT topic. For example,/topic TOPIC_MATCH 'sensors/+/temperature'applies MQTT wildcard rules to the field value. - Migrating clients can keep MQTT wildcard syntax on a per-request basis with
topic_matching_policy=mqtton commands such assubscribe,sow, andsow_and_subscribe. - Use
LIKEonly when you intentionally want PCRE behavior regardless of the resolved topic policy. - Choose the SOW key from the business entity, not from the topic alone, when one MQTT topic carries repeated updates for the same device or asset.
- Use
sow_and_subscribeagainst the Union or View to hydrate an operator screen atomically, then keep it up to date without a query gap. - Use
sow_and_delta_subscribeor aConflatedTopicfor browser-based dashboards that do not need every intermediate update.