MQTT API definitions for the Bridge add-on of the ESP RainMaker Neo platform.
A bridge is a RainMaker node that fronts one or more non-IP child devices
(Zigbee, Matter-bridge, etc.). Children are represented as their own AWS IoT
Things named <parent>--<suffix>; the bridge publishes and subscribes on
their behalf. This spec documents the MQTT surface that is specific to the
bridge feature:
addChild / removeChild) and its bridgeAck reply;The bridge is a fully optional add-on. MQTT_Node.yaml documents the
canonical node topics and owns every payload schema shared with a direct
device; this spec depends one-way on those definitions, references them by
name, and does not restate them.
AWS IoT Core endpoint (region-specific, TLS mutual auth)
X.509 certificate-based mutual TLS authentication with AWS IoT Core. A
bridge authenticates with its own certificate, and its policy extends
the standard device grants to Things named <self>--* — that is, to its
own children and to nothing else. A bridge can neither read nor write
traffic addressed to another bridge's children.
[Bridge → Cloud] Dedicated control-plane channel for child-Thing
lifecycle (addChild, removeChild).
A bridge can only publish on its own control plane: the publishing client
ID is checked against the {parentNodeId} segment and a mismatch is
dropped.
The basic-ingest variant
$aws/rules/bridge_to_cloud_rule/rainmaker/bridges/{parentNodeId}/to_cloud
is also accepted, and must name bridge_to_cloud_rule. Basic ingest skips
the broker and reaches only the rule named in the path, so addressing
node_to_cloud_rule here would silently drop the request.
Replies are published back on the bridge's own fromCloud channel
(rainmaker/nodes/{parentNodeId}/from_cloud) as a bridgeAck event.
Bridge publishes child-lifecycle control events (addChild / removeChild)
Dedicated control-plane channel for child-Thing lifecycle. Replies arrive
on the bridge's own fromCloud channel as a bridgeAck event
(subscribeBridgeAck).
Available only on servers:
Bridge thing name (the parent in a <parent>--<suffix> child
relationship). Bridge thing names are guaranteed by registration not to
contain --.
Accepts the following message:
Bridge-only child-Thing lifecycle control event
Bridges publish child-lifecycle requests on
rainmaker/bridges/{parentNodeId}/to_cloud. The cloud dispatches on the
event array and replies as a bridgeAck event on the bridge's own
fromCloud channel (rainmaker/nodes/{parentNodeId}/from_cloud).
Send exactly one of addChild / removeChild per publish:
bridgeAck is a single object, so only the first is honoured and the
rest are ignored.
Bridge requests creation of a new child Thing
{
"event": [
"addChild"
],
"addChild": {
"request_id": "8b51c2a4",
"child_suffix": "child_A",
"child_local_id": "0x00158D00012345AB"
}
}
Bridge requests removal of an existing child Thing
{
"event": [
"removeChild"
],
"removeChild": {
"request_id": "9c52d3b5",
"child_node_id": "bridge-hub-001--child_A"
}
}
[Cloud → Bridge] The bridge's own core fromCloud channel. In
addition to the standard cloud responses (see fromCloudMessage in
MQTT_Node.yaml), this is where the bridgeAck reply to an addChild /
removeChild request arrives.
Bridge receives the bridgeAck reply to addChild / removeChild
The cloud replies to a control-plane request as a bridgeAck event on the
bridge's own fromCloud topic
(rainmaker/nodes/{parentNodeId}/from_cloud) — the same core channel a
node uses for cloud responses.
Available only on servers:
Bridge thing name (the parent in a <parent>--<suffix> child
relationship). Bridge thing names are guaranteed by registration not to
contain --.
Accepts the following message:
Response to an addChild / removeChild request
Response to an addChild or removeChild request published on the
bridge control-plane channel (bridgeToCloud). Arrives on the bridge's
own fromCloud (rainmaker/nodes/{parentNodeId}/from_cloud) as a
bridgeAck event, alongside the standard core fromCloud events.
Cloud confirms child creation on the bridge's from_cloud
{
"event": [
"bridgeAck"
],
"bridgeAck": {
"request_id": "8b51c2a4",
"status": "success",
"child_node_id": "bridge-hub-001--child_A"
}
}
[Cloud → Bridge] A child's from_cloud traffic, rewritten onto the
bridge namespace so the bridge can pick up every child's cloud→device
messages with one wildcard subscription:
rainmaker/bridges/{self}/children/+/from_cloud.
The payload is republished unchanged, so its shape is identical to the
core fromCloud channel.
Bridge receives a child's cloud→device traffic on the bridge namespace
Every publish to rainmaker/nodes/{child}/from_cloud is rewritten onto
the bridge namespace, so a single wildcard subscription on the bridge
covers all of its children. The payload is republished unchanged and is
identical to the core fromCloud channel.
Available only on servers:
Bridge thing name (the parent in a <parent>--<suffix> child
relationship). Bridge thing names are guaranteed by registration not to
contain --.
Bridged child thing name, of the form <parent>--<suffix>, where
<suffix> matches ^[a-zA-Z0-9_]{1,32}$.
Accepts the following message:
A child's cloud→device message, rewritten onto the bridge namespace
Identical to the core fromCloudMessage (MQTT_Node.yaml) — the
rewrite republishes the payload unchanged.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Cloud → Bridge] A child's unicast parameter-control traffic,
rewritten onto the bridge namespace. The bridge picks every child's
commands up with one wildcard subscription:
rainmaker/bridges/{self}/children/+/user/+/params.
The wildcard over the shadow-name segment is deliberate: a child's unicast shadow name changes whenever its subgroup set changes, and the wildcard lets the existing subscription keep matching without any subscribe/unsubscribe churn.
The payload is republished unchanged, so its shape is identical to the
core userParams channel.
Bridge receives a child's unicast parameter control on the bridge namespace
Every publish to
rainmaker/nodes/{child}/user/params-{groupInfoStr}/params is rewritten
onto the bridge namespace. The payload is republished unchanged and is
identical to the core userParams channel.
Available only on servers:
Bridge thing name (the parent in a <parent>--<suffix> child
relationship). Bridge thing names are guaranteed by registration not to
contain --.
Bridged child thing name, of the form <parent>--<suffix>, where
<suffix> matches ^[a-zA-Z0-9_]{1,32}$.
Group info string: <group_id>[-<sub1>-<sub2>-…] with subgroups sorted
alphabetically. Empty string if unassociated. See MQTT_Node.yaml.
Accepts the following message:
A child's unicast parameter control, rewritten onto the bridge namespace
Identical to the core paramControlMessage (MQTT_Node.yaml) — the
rewrite republishes the payload unchanged.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Bridge → Cloud] Core node→cloud channel. A bridge publishes its own
and its children's setNodeConfig here; {nodeId} is the bridge or a
child Thing. Payload schema is the core toCloudMessage
(MQTT_Node.yaml), unchanged for a child.
Child-Thing lifecycle (addChild / removeChild) is not carried
here — it has its own bridgeToCloud control plane.
Basic-ingest variant
$aws/rules/node_to_cloud_rule/rainmaker/nodes/{nodeId}/to_cloud is
granted for children too. The rule is the core one: a child's publish
is ingested by exactly the same rule as a direct device's.
Bridge publishes its own and its children's setNodeConfig on the core to_cloud
A bridge publishes setNodeConfig for itself and for each child on the
core rainmaker/nodes/{nodeId}/to_cloud channel, with {nodeId} set
to the bridge or to a child Thing. The payload schema is identical to a
direct device's — bridge-ness is carried in Thing attributes, never in the
config. See toCloudMessage in MQTT_Node.yaml.
Available only on servers:
Node identifier (Thing Name / MQTT Client ID). For bridge-ridden core topics this is the bridge or a child Thing.
Accepts the following message:
A node→cloud event, published by the bridge for itself or a child
Identical to the core toCloudMessage (MQTT_Node.yaml) — refer to it
for the setNodeConfig payload and its examples, for both the default
and the Matter data models. A child's config is byte-for-byte a direct
device's: the parent link is recorded in the child's Thing attributes,
never in the config payload.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Bridge → AWS IoT Shadow] Core named shadow update, published by the
bridge on behalf of a child with {nodeId} set to the child Thing.
Fire-and-forget at QoS 1 — the bridge does NOT subscribe to
/update/accepted or /update/rejected for children. Payload schema is
the core namedShadowUpdateMessage (MQTT_Node.yaml).
Deleting a child's stale shadow after a group or subgroup move is not a bridge operation. The cloud migrates the shadow as part of the group flow, so there is no bridge-published shadow delete.
Bridge publishes a child's named shadow on the core canonical topic
A bridge publishes its children's shadow updates directly on the core
canonical topic with {nodeId} set to the child Thing. The model is
fire-and-forget at QoS 1: bridges do not subscribe to
/update/accepted or /update/rejected for children, which is what keeps
the per-bridge subscription count independent of the number of children.
Available only on servers:
Node identifier (Thing Name / MQTT Client ID). For bridge-ridden core topics this is the bridge or a child Thing.
Group info string: <group_id>[-<sub1>-<sub2>-…] with subgroups sorted
alphabetically. Empty string if unassociated. See MQTT_Node.yaml.
Accepts the following message:
A named shadow update, published by the bridge for itself or a child
Identical to the core namedShadowUpdateMessage (MQTT_Node.yaml) —
refer to it for the state.reported.params payload and its examples,
for both the default and the Matter data models. For a child, the bridge
sets online from protocol-side reachability, and reports the child's
own ncfg_ver (the SHA-256 of that child's config, emitted once the
cloud acknowledges its setNodeConfig), never the bridge's.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Bridge → Cloud] Core timeseries channel, published by the bridge on
behalf of a child with {nodeId} set to the child Thing. Server-side
ingestion is identical to a direct device's. Payload schema is the core
timeseriesMessage (MQTT_Node.yaml). Basic-ingest variant
$aws/rules/node_ts_rule/rainmaker/nodes/{nodeId}/ts/{groupInfoStr}.
Bridge publishes a child's timeseries on the core canonical topic
A bridge publishes its children's timeseries directly on the core
canonical topic with {nodeId} set to the child Thing. Server-side
ingestion is identical to a direct device's.
Available only on servers:
Node identifier (Thing Name / MQTT Client ID). For bridge-ridden core topics this is the bridge or a child Thing.
Group info string: <group_id>[-<sub1>-<sub2>-…] with subgroups sorted
alphabetically. Empty string if unassociated. See MQTT_Node.yaml.
Accepts the following message:
A child's timeseries point, published by the bridge
Identical to the core timeseriesMessage (MQTT_Node.yaml). Ingestion
resolves the child from the topic exactly as it does a direct device.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Bridge → Cloud] Core batched timeseries channel, published by the
bridge on behalf of a child with {nodeId} set to the child Thing.
Payload schema is the core timeseriesBatchMessage (MQTT_Node.yaml),
including its 1-100 points-per-message guidance. Basic-ingest variant
$aws/rules/node_ts_batch_rule/rainmaker/nodes/{nodeId}/ts/{groupInfoStr}/batch.
Bridge publishes a child's batched timeseries on the core canonical topic
Batched form of publishChildTimeseries, with {nodeId} set to the child
Thing.
Available only on servers:
Node identifier (Thing Name / MQTT Client ID). For bridge-ridden core topics this is the bridge or a child Thing.
Group info string: <group_id>[-<sub1>-<sub2>-…] with subgroups sorted
alphabetically. Empty string if unassociated. See MQTT_Node.yaml.
Accepts the following message:
A child's batched timeseries points, published by the bridge
Identical to the core timeseriesBatchMessage (MQTT_Node.yaml),
including the 1-100 independently queryable points per message.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Bridge → Cloud] Core notification channel, published by the bridge on
behalf of a child with {nodeId} set to the child Thing. Payload schema
is the core notificationMessage (MQTT_Node.yaml). Basic-ingest variant
$aws/rules/node_notify_rule/rainmaker/nodes/{nodeId}/notify/{groupInfoStr}.
Bridge publishes a child's notification on the core canonical topic
A bridge publishes its children's notifications directly on the core
canonical topic with {nodeId} set to the child Thing.
Available only on servers:
Node identifier (Thing Name / MQTT Client ID). For bridge-ridden core topics this is the bridge or a child Thing.
Group info string: <group_id>[-<sub1>-<sub2>-…] with subgroups sorted
alphabetically. Empty string if unassociated. See MQTT_Node.yaml.
Accepts the following message:
A child's notification, published by the bridge
Identical to the core notificationMessage (MQTT_Node.yaml).
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
{}
[Bridge → AWS IoT Shadow] Core indexed shadow update, published by the
bridge on behalf of a child with {nodeId} set to the child Thing. This
is where a child's online flag lives, because AWS IoT presence never
fires for a child.
After reconnecting, a bridge must reconfirm each child and re-report
online: true per child; nothing restores it automatically. That is a
burst proportional to the number of children, so spread the publishes
rather than sending them back to back. Payload schema is the core
indexedShadowUpdateMessage (MQTT_Node.yaml).
Bridge reports a child's online state on the core indexed shadow
A child holds no MQTT connection of its own, so AWS IoT presence events
never fire for it. Its user-facing online state comes from the bridge
writing online to the child's iparams shadow as it observes the child
on the bridge-side protocol.
The cloud writes this topic too: when the bridge disconnects, every
one of its children is marked online: false. There is no symmetric
behaviour on connect — after reconnecting, the bridge must reconfirm each
child's reachability and re-report online: true itself.
Available only on servers:
Node identifier (Thing Name / MQTT Client ID). For bridge-ridden core topics this is the bridge or a child Thing.
Accepts the following message:
A child's indexed-shadow update, carrying its online state
Identical to the core indexedShadowUpdateMessage (MQTT_Node.yaml).
For a child this is the authoritative source of online, since AWS IoT
presence never fires for a device that holds no MQTT connection.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
Bridge reports a child reachable on the protocol side
{
"state": {
"reported": {
"online": true
}
}
}
Bridge-only child-Thing lifecycle control event
Bridges publish child-lifecycle requests on
rainmaker/bridges/{parentNodeId}/to_cloud. The cloud dispatches on the
event array and replies as a bridgeAck event on the bridge's own
fromCloud channel (rainmaker/nodes/{parentNodeId}/from_cloud).
Send exactly one of addChild / removeChild per publish:
bridgeAck is a single object, so only the first is honoured and the
rest are ignored.
Response to an addChild / removeChild request
Response to an addChild or removeChild request published on the
bridge control-plane channel (bridgeToCloud). Arrives on the bridge's
own fromCloud (rainmaker/nodes/{parentNodeId}/from_cloud) as a
bridgeAck event, alongside the standard core fromCloud events.
A node→cloud event, published by the bridge for itself or a child
Identical to the core toCloudMessage (MQTT_Node.yaml) — refer to it
for the setNodeConfig payload and its examples, for both the default
and the Matter data models. A child's config is byte-for-byte a direct
device's: the parent link is recorded in the child's Thing attributes,
never in the config payload.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A named shadow update, published by the bridge for itself or a child
Identical to the core namedShadowUpdateMessage (MQTT_Node.yaml) —
refer to it for the state.reported.params payload and its examples,
for both the default and the Matter data models. For a child, the bridge
sets online from protocol-side reachability, and reports the child's
own ncfg_ver (the SHA-256 of that child's config, emitted once the
cloud acknowledges its setNodeConfig), never the bridge's.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A child's indexed-shadow update, carrying its online state
Identical to the core indexedShadowUpdateMessage (MQTT_Node.yaml).
For a child this is the authoritative source of online, since AWS IoT
presence never fires for a device that holds no MQTT connection.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A child's cloud→device message, rewritten onto the bridge namespace
Identical to the core fromCloudMessage (MQTT_Node.yaml) — the
rewrite republishes the payload unchanged.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A child's unicast parameter control, rewritten onto the bridge namespace
Identical to the core paramControlMessage (MQTT_Node.yaml) — the
rewrite republishes the payload unchanged.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A child's timeseries point, published by the bridge
Identical to the core timeseriesMessage (MQTT_Node.yaml). Ingestion
resolves the child from the topic exactly as it does a direct device.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A child's batched timeseries points, published by the bridge
Identical to the core timeseriesBatchMessage (MQTT_Node.yaml),
including the 1-100 independently queryable points per message.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
A child's notification, published by the bridge
Identical to the core notificationMessage (MQTT_Node.yaml).
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.
See the referenced core message schema in MQTT_Node.yaml for the
authoritative payload definition and examples.