Technical Standards
MicroDCS is built around open standards for messaging, payload modeling, observability, and industrial domain semantics. This page summarizes the main standards used by the framework and explains how they are applied in the current architecture.
MQTT v5
MQTT v5 is the primary transport for event-driven communication in MicroDCS. The framework uses MQTT features not just for message delivery, but also for request-response flows, delivery coordination, scaling, and time-bounded processing.
Standard: MQTT Version 5.0
Request / Response
MQTT v5 supports request-response interaction through Response Topic and Correlation Data. The Request Response Information and Response Information fields standardize the communication channel, but not the full response-handling behavior. In practice, brokers such as Mosquitto transport these attributes without managing the response flow for the application. MicroDCS therefore creates an instance-specific response channel and subscribes to it at startup to handle error and correlation backchannels. Published request-response messages are also expected to target topics with active subscribers, which corresponds to successful delivery with PUBACK=0x00.
The MQTT
Correlation Datafield in request/response flows carries the CEidof the originating request event. Because a request is a root event it has nocausationid, so the mapper falls back toid(see CloudEvents MQTT mapping below). The responder echoesCorrelation Databack unchanged, allowing the requester to match the response to its original request.
sequenceDiagram
autonumber
participant Device
participant Device Connector
participant Broker
participant DCS
Note over Device, Device Connector: Device Connector is optional
Device Connector->>Broker: Subscribe<br/>[topic: mydevice/event]
DCS->>Broker: Subscribe<br/>[topic: +/event]
DCS->>Broker: Subscribe<br/>[topic: dcs/errors/<dcs_id>]
Device->>Device Connector: Request<br/>[any protocol]
Device Connector->>Broker: Request<br/>[topic: mydevice/event<br/>responsetopic: mydevice/command<br/>correlationdata: <cid>]
Broker->>DCS: Request [topic: mydevice/event<br/>responsetopic: mydevice/command<br/>correlationdata: <cid>]
DCS->>Broker: Response [topic: mydevice/command<br/>responsetopic:dcs/errors/<dcs_id><br/>correlationdata: <cid>]
opt Error Response
Broker->>DCS: Error Response [topic:dcs/errors/<dcs_id><br/>correlationdata: <cid>]
end
Broker->>Device Connector: Response [topic: mydevice/command<br/>responsetopic:dcs/errors/<dcs_id><br/>correlationdata: <cid>]
Device Connector->>Device: Response<br/>[any protocol]
Message Expiry Interval
MQTT v5 introduced Message Expiry Interval so publishers can set a bounded lifetime for time-sensitive messages. This helps reclaim control over message flow once a message is no longer useful. Depending on timing and broker behavior, the broker may discard the message before delivery, or the receiver may discard it after inspecting the remaining interval.
sequenceDiagram
participant Publisher
participant Broker
participant Subscriber
activate Broker
activate Publisher
activate Subscriber
Subscriber->>Broker: Disconnect
deactivate Subscriber
Publisher->>Broker: Publish<br/>[topic: demo<br/>correlationdata: <cid><br/>messageexpiryinterval: 10]
activate Publisher
Publisher->>Publisher: MessageExpirationTask<br/>[correlationdata: <cid>,<br/>timer: 10]
Note over Broker: After 10s
Publisher->>Publisher: HandleExpiration
deactivate Publisher
Publisher->>Broker: Publish<br/>[topic: demo<br/>correlationdata: <cid><br/>messageexpiryinterval: 60]
activate Publisher
Publisher->>Publisher: MessageExpirationTask<br/>[correlationdata: <cid><br/>timer: 60]
Note over Broker: After 30s
Subscriber->>Broker: Connect
activate Subscriber
Broker->>Subscriber: Publish<br/>[topic: demo<br/>correlationdata: <cid><br/>messageexpiryinterval: 30]
Subscriber->>Broker: Publish<br/>[topic: demo<br/>correlationdata: <cid><br/>messageexpiryinterval: 60]
Broker->>Publisher: Publish<br/>[topic: demo<br/>correlationdata: <cid><br/>messageexpiryinterval: 60]
Publisher->>Publisher: StopExpirationTask
deactivate Publisher
deactivate Subscriber
deactivate Publisher
deactivate Broker
Shared Subscriptions
To achieve higher availability or scale out processing across multiple container instances or MQTT clients, MicroDCS can use MQTT v5 shared subscriptions. A shared subscription is identified through a special topic-filter format: $share/{ShareName}/{filter}.
$shareis a literal string that marks the Topic Filter as being a Shared Subscription Topic Filter.{ShareName}is a character string that does not include "/", "+" or "#"{filter}The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription.
With QoS 1, shared subscriptions provide load balancing so each message is delivered to one client in the shared group. They do not eliminate duplicate delivery, however. Publishers may resend when acknowledgments are missing, so consumers still need deduplication based on message identity or payload semantics.
Quality of Service
The QoS level used to deliver an Application Message outbound to the Client could differ from that of the inbound Application Message.
Setting a response topic in the application sets QoS=1 (at least once delivery) where we want to make sure it arrives at the destination, otherwise its a QoS=0 (at most once delivery) notification that can be lost.
Retained Messages
MQTT retained messages allow the broker to store the last message published to a topic with the RETAIN flag set. When a new client subscribes to that topic, the broker delivers the stored message immediately — the subscriber does not need to wait for the next publish.
MicroDCS uses retained messages for the northbound MES publishing interface. The Job Order Publisher maintains per-job and per-scope retained topics so that a reconnecting MES client can recover full state without replaying the event stream.
Retained topics use MQTT v5 MessageExpiryInterval to auto-expire stale data (default 48 hours, configurable via APP_PUBLISHER_RETAINED_TTL_SECONDS). Deleting a retained topic is done by publishing a zero-byte retained message to the same topic, which instructs the broker to discard the stored message.
See Machinery Jobs – MES Northbound Publishing for the full topic layout and payload schemas.
MessagePack-RPC
MessagePack-RPC is supported as an additional transport option where a lightweight binary RPC channel is preferred.
MicroDCS also supports outgoing CloudEvents over MessagePack by publishing RPC NOTIFICATION frames to connected clients.
CloudEvents
CloudEvents provides the common event envelope used across transports. It allows MicroDCS to carry typed payloads, metadata, tracing information, and delivery attributes in a consistent way.
Overview and Spec
- CloudEvents primer: versioning of CloudEvents
- CloudEvents specification
- CloudEvents distributed tracing extension
- CloudEvents expiry time extension
- CloudEvents recorded time extension
- CloudEvents correlation extension
MQTT and MessagePack
CloudEvents defines an MQTT binding, which MicroDCS uses as the basis for transport mapping.
Because MicroDCS targets MQTT v5, it implements the binding in Binary Content Mode:
datacontenttypeis mapped to the MQTT v5ContentTypeproperty.expiryintervalis mapped toMessageExpiryInterval.- All other CloudEvent attributes — including
id,source,subject,type,dataschema,correlationid,causationid, and entries incustommetadata— are transported as MQTTUserPropertyfields using the attribute name unchanged, as required by the CloudEvents MQTT binding spec. - Other MQTT-specific properties are read from and written to
transportmetadata.
As a secondary mapping for request/response flows, the MQTT Correlation Data property is populated with causationid if present, falling back to id for root/initiating events (causationid ?? id). This lets MQTT-native consumers match a response to its originating request without parsing UserProperty fields, while the primary CE attributes remain intact in UserProperty. The responder echoes Correlation Data back unchanged, as required by the MQTT v5 spec.
Note: despite the name similarity, the MQTT
Correlation Datafield does not correspond to the CEcorrelationidattribute.correlationidis a group-level transaction tag shared by all events in a flow and is carried exclusively as aUserProperty.Correlation Datais a per-request/response matching token that corresponds semantically tocausationid.
For MessagePack transport, the CloudEvent is sent as a structured object, with custommetadata serialized into individual attributes. Transport-specific metadata is carried separately alongside the CloudEvent.
JSON Schema
JSON Schema is used to define application payload models that can be turned into typed Python dataclasses.
OpenTelemetry
OpenTelemetry provides the tracing and metrics foundation for runtime observability across handlers and processors.
- OpenTelemetry Python zero-code instrumentation
- OpenTelemetry for Python
- OpenTelemetry messaging semantic conventions
- OpenTelemetry RPC semantic conventions
IEC 61131-3 SFC
The SFC recipe schema uses IEC 61131-3 Sequential Function Chart terminology — steps, transitions, action qualifiers (N, P, S, R, L, D, etc.), and selection/simultaneous divergence — to define machine-readable recipes without the graphical/PLC baggage of PLCopen TC6 XML. See SFC Engine for the recipe format and engine architecture.