创建 MQTT 产品
接入方式选 MQTT,联调期建议打开 allowInsert。
这页复用 MQTT 任意主题 / 第三方 Broker 接入说明,方便在当前目录下直接查看。
自建 MQTT 接入适合下面这类设备:
要先说明一件很容易误解的事:
"任意主题设备"不等于"只能透传"。
在自建接入模式里,你仍然可以把主题类型配置成:
THING_MODEL:消息体已经是标准物模型 JSON。PASSTHROUGH:消息体还是厂商自定义格式,需要编解码。接入方式选 MQTT,联调期建议打开 allowInsert。
填 host、port、username、password、clientIdPrefix。
每条映射填 topicPattern + topicCategory + productKey + qos。
产品详情 → 连接信息 → 管理自建接入,切到自建接入模式,再添加设备。
进入设备详情 → 设备连接信息,直接复制自建 host、账号、ClientID。
脚本里写 preDecode 提取 deviceId,透传再补 decode/encode。
任意主题模式里,最容易混的是"到底该在哪一层配"。
| 对象 | 你在哪里配 | 它负责什么 |
|---|---|---|
| 产品 | 产品管理 | 定义产品标识、物模型、编解码、自动注册和下行主题 |
| 连接信息 | 产品详情 → 连接信息 | 绑定自建 MQTT 网络组件,查看当前接入模式 |
| MQTT 网络组件 | 网络组件 → MQTT | 连接第三方 Broker,订阅任意 Topic,做主题映射 |
| 协议脚本 | 产品驱动 / IDE 调试器 | 识别设备,并转换上行、下行数据 |
设备发布的是真实 Topic,平台配置的是用于订阅的 Topic 模式。这两者不一定完全相同。
例如设备实际发布:
mqtt/device001/PublishEvent如果同一产品下有多个设备,平台应配置:
mqtt/+/PublishEvent这里的 + 只匹配一层内容,因此可以匹配 device001、device002 等设备编号;它不会出现在平台发给设备的实际 Topic 中。# 可以匹配后续多层内容,范围更宽,联调时不建议直接使用。
如果只接入一个固定设备,也可以直接配置完整 Topic:
mqtt/device001/PublishEvent文档中的 <deviceId>、<productKey> 只是“这里填实际值”的说明写法,不是要原样填入配置框的文字。
设备回复和平台下行也要使用实际 Topic。例如:
| 用途 | 示例 |
|---|---|
| 设备上行 | mqtt/device001/PublishEvent |
| 设备回复 | mqtt/device001/PublishEvent/ack |
| 平台下行 | mqtt/device001/OperateDevice |
回复和下行 Topic 不要再作为上行消息订阅,否则平台可能把自己发出的消息再次当成设备上报。
任意主题模式下,平台大致按这个顺序处理:
preDecode),获取 deviceId。THING_MODEL,平台按标准 JSON 继续处理;如果是 PASSTHROUGH,上行使用 decode,下行需要时再使用 encode。这里有两个关键细节:
deviceId。在产品管理里新建产品时,接入方式还是选 MQTT。
第一次联调时,产品层建议先确认这 3 项:
allowInsert):联调期可暂时开启,正式环境建议按实际需求控制。downTopic):如果设备订阅固定主题,先配置完整 Topic。
网络组件负责的是"平台怎么去连 Broker",不是"设备怎么连平台"。
第一次联调时,先把这些基础连接参数填好:
| 字段 | 作用 |
|---|---|
host | 第三方 Broker 地址 |
port | Broker 端口 |
username | Broker 账号 |
password | Broker 密码 |
clientIdPrefix | 平台作为客户端连上去的 ClientID 前缀 |
connectTimeout | 连接超时时间(毫秒) |

进入网络组件详情 → 主题订阅,逐条添加要订阅的 Topic。
每一条主题映射,最关键的配置是:
| 字段 | 作用 | 第一次联调建议 |
|---|---|---|
订阅 Topic(页面字段通常为 topicPattern) | 平台实际订阅的主题模式,支持 + 和 # | 先用最小范围,不要一上来订 # |
消息格式(页面字段通常为 topicCategory) | 按物模型还是透传处理 | 必填 |
qos | MQTT QoS | 一般先用 1 |
| 产品 | 把这条 Topic 明确归属到哪个产品 | 建议直接选择产品 |
enabled | 是否启用 | 联调时保持启用 |
消息格式选择规则:
| 选项 | 什么时候选 |
|---|---|
THING_MODEL | payload 已经是标准物模型 JSON |
PASSTHROUGH | payload 还是私有协议,需要编解码 |

用主题模式测试工具
网络组件详情页有一个"主题模式测试工具",输入设备实际 Topic,立刻告诉你能否匹配、匹配到了哪个产品。联调时强烈推荐先在这里自测一次。

路径就在 产品详情 → 连接信息:
自建接入。新版本推荐直接从 设备详情 拿连接信息,不用再回产品详情翻。
路径:设备管理 → 新增设备 → 设备详情 → 设备连接信息。
自建接入模式下,页面会直接给出:
host / portUsername / Password:来自网络组件配置ClientID:按下面规则拼好并支持一键复制自建接入 ClientID 规则
ClientID = ProductKey.DeviceIdhost、用户名、密码都来自产品绑定的 MQTT 网络组件。
任意主题模式下,真正最容易卡住的是 deviceId。
平台会执行产品脚本里的 preDecode 去识别设备号。识别来源可以是:
下面这个例子演示从 mqtt/device001/PublishEvent 的第二段取设备号:
var preDecode = (payload, topic) => {
var parts = topic.split("/");
if (parts.length != 3 || parts[0] != "mqtt" || parts[2] != "PublishEvent") {
throw new Error("unexpected uplink topic");
}
return { deviceId: parts[1] };
};如果脚本没有识别出设备号,且产品允许自动注册,平台可能会先把消息放到系统预置的调试设备(设备 ID 为 nexiotDebugDeviceId)。这只是联调兜底,正式接入必须返回稳定的真实 deviceId。
如果消息是透传模式,还要继续补:
decode:把设备上报转成属性或事件。encode:把平台下发转成设备能识别的报文。如果设备订阅的下行 Topic 不是平台默认主题,第一次联调建议先在产品里把 downTopic 固定住。
下行 Topic 可以使用占位符,平台发送时会替换成实际值。常用写法是:
产品:{{productKey}}
设备:{{deviceId}}如果页面提示了其他占位符写法,以页面提示为准。
订阅 Topic 中的 +、# 只用于匹配上行消息,不能直接当成下行 Topic。下行时必须生成具体设备 Topic。

如果你在 decode 结果里返回了 replyPayload,平台会自动尝试回复。
自动回复踩坑提醒
replyPayload 的结果,平台就回 1 次。replyPayload,平台就会回 10 次。联调期通常只建议保留一条回复。

建议按这个顺序来:
preDecode,确认能稳定拿到 deviceId。decode 和 encode。mqtt/device001/PublishEvent,却把 mqtt/<deviceId>/PublishEvent 原样填入订阅配置。应根据实际情况填写完整 Topic 或 mqtt/+/PublishEvent。preDecode 没返回稳定的 deviceId。继续排查可以直接看 MQTT 常见问题。
任意 Topic 接入至少要确认下面几项:
| 检查项 | 需要确认的内容 |
|---|---|
| 产品 | 接入方式为 MQTT,物模型已保存,已绑定正确的自建 MQTT 网络 |
| 网络 | Broker 地址和认证信息正确,网络处于运行状态 |
| 主题 | 上行 Topic 能匹配,已明确关联产品,消息格式选择正确 |
| 设备 | preDecode 能稳定识别设备 ID,或已按产品策略准备自动注册 |
| 下行 | 设备实际订阅的下行 Topic 已配置,必要时补充 encode |
推荐先发送一条无副作用的心跳或测试消息,依次确认:平台收到消息、识别到正确设备、物模型产生数据、回复或下行 Topic 正确。
一个 MQTT 网络可以被多个产品复用,因此每条上行订阅都要明确它属于哪个产品。
因此需要注意:
#。当一个 MQTT 网关下挂多个传感器、仪表或 Modbus 从设备时,网关和子设备需要分别建立产品与设备关系。
| 对象 | 作用 |
|---|---|
| 网关产品 | 配置 MQTT 网络、订阅网关上行 Topic、解析网关报文 |
| 网关设备 | 表示实际连接 Broker 的那台网关 |
| 子设备产品 | 定义子设备的物模型和编解码规则 |
| 子设备 | 表示网关下挂的具体传感器或仪表 |
通常只有网关产品订阅任意 Topic。子设备不需要重复订阅同一个 Topic,网关收到报文后再把数据分发给对应子设备。
网关上报消息
↓
识别网关设备
↓
解析出子设备编号、地址或其他标识
↓
匹配子设备产品和设备
↓
更新子设备属性、事件和状态网关解析报文时,需要同时输出两类信息:
字段名称由设备协议和脚本约定决定,关键是每次上报都能用同一编号找到同一子设备。
decode 必须与网关转发的实际数据一致。常见的 Modbus 子设备 ID 形式是:
网关设备ID-从站地址例如网关设备 ID 为 gateway-001、从站地址为 2,子设备 ID 可以是 gateway-001-2。如果厂商已有自己的编号规则,应以厂商规则为准。
平台控制网关子设备时,消息通常仍然通过网关发送:
encode 生成子设备命令。下行 Topic 需要区分网关和子设备信息。配置时按页面支持的占位符填写网关设备 ID、子设备 ID;如果厂商只要求网关 Topic,就使用网关产品的下行 Topic。不要把 +、# 直接写入下行 Topic,也不要把网关设备 ID 和子设备 ID 混用。
如果没有编写 preDecode,且产品允许自动注册,平台可能会先把消息放到调试设备 nexiotDebugDeviceId。这只能帮助联调主消息,不能代替真实的网关与子设备关系配置。
要验证子设备接入成功,至少需要同时看到:
| 现象 | 优先检查 |
|---|---|
| 网关有数据,子设备没有数据 | 网关 decode 是否返回子设备标识,子设备是否已创建并关联网关 |
| 子设备设备 ID 不断变化 | 子设备 ID 生成规则是否稳定,是否使用了固定地址或序列号 |
| 子设备命令没有到达 | 网关连接是否正常,下行 Topic 是否使用了正确的网关和子设备占位符 |
| 所有数据都进入调试设备 | preDecode 是否能识别真实网关 ID,是否误用了自动注册兜底 |
| 一条报文包含多个子设备但只有一个有数据 | 检查协议是否为每个子设备返回独立的解析结果,并进行实际联调验证 |
网关和子设备的具体字段会因设备协议不同而变化,但总体原则都是:网关负责连接和转发,子设备负责独立的产品模型和数据归属。