艾格伦IoT开发者文档 返回管理门户
DEVICE INTEGRATION · V1.4

MQTT 真机接入指南

从平台创建设备,到 MQTTX、命令行和 Python 发布真实遥测数据,全部使用 TLS 与独立设备账号。

公网 MQTTS 端点 47.94.172.189:8883
TLS 设备入口
协议
MQTT 3.1.1
认证
账号 + 密码
Client ID
必须等于设备 ID
三条必须遵守的规则

Client ID 必须与设备 ID 完全一致;只向 devices/<设备ID>/telemetry 发布;Payload 顶层必须包含字符串 iccid,并至少包含 1 个有限 JSON 数字监测值。设备不需要客户端证书,但必须使用平台 CA 校验服务器证书。

01

接入参数

真机和调试工具均使用同一套 MQTTS 契约。

服务地址47.94.172.189
端口8883 / TCP
连接 URImqtts://47.94.172.189:8883
推荐协议MQTT 3.1.1
TLS1.2 或更高
认证设备账号 + 密码
客户端证书不需要
服务器校验必须使用 ca.crt
Client ID与设备 ID 相同
遥测 QoS推荐 1,不 Retain
i

8883 是原生 MQTT over TLS,不是 HTTPS 或 WSS。门户使用 HTTPS 443;明文 MQTT 1883 不应对公网开放。

02

管理员创建设备

每台真机都应有独立设备记录和独立凭据。

  1. 1
    填写设备信息

    填写唯一设备 ID、名称、位置和归属账号;创建设备时不填写 ICCID。

  2. 2
    保存一次性凭据

    立即保存 Client ID、用户名和密码;关闭凭据窗口后不能再次查看原密码。

  3. 3
    下载公共 CA

    将平台提供的 ca.crt 安装到设备或调试工具中。

  4. 4
    设备自动上传 ICCID

    固件从通信模组自动读取,无需用户填写;无法读取外置卡时自动上传字符串 "0"。

ICCID 遥测上报规则
场景遥测值说明
无法读取外置卡"0"必须是字符串,不能上传 JSON 数字 0
内置蜂窝卡"<18-22位数字>"只允许数字,并保留前导零;平台自动写入设备资料

API 请求结构

POST /portal-api/v1/devices
Content-Type: application/json
X-CSRF-Token: <当前管理员会话令牌>

{
  "id": "device-001",
  "name": "一号温度采集器",
  "protocol": "MQTT",
  "location": "一号车间",
  "ownerUserId": 2
}

示例没有现网密码。管理员接口使用门户会话和 CSRF 防护,不应从设备固件直接调用。

03

TLS 与 CA 证书

无需客户端证书,但服务器身份校验不能省略。

设备只需要公共 CA

配置平台提供的 ca.crt。客户端证书和客户端私钥留空;不得复制 Broker 私钥、CA 私钥或任何服务端私钥。

  • 验证 Broker 证书链、有效期和 hostname/IP。
  • 设备建立 TLS 前先完成可靠时间同步。
  • 证书轮换时,通过可信渠道更新设备中的 CA。
  • 禁止使用 --insecure、CERT_NONE、tls_insecure_set(true) 或关闭 hostname 校验。
04

设备身份与 Topic

设备 ID 同时决定 Client ID 和遥测 Topic。

Client ID<设备ID>
遥测 Topicdevices/<设备ID>/telemetry
项目要求错误示例
Client ID与设备 ID 完全相同device-001-debug
Topicdevices/device-001/telemetry其他设备前缀或大小写不同
并发调试同一设备凭据只保持一个连接真机与 MQTTX 同时连接

两个客户端使用同一个 Client ID 时会互相顶掉连接。调试真机前先关闭 MQTTX 或其他模拟程序。当前只以遥测 Topic 为正式接入契约,不要假设 status、event 或 command 等 Topic 已被授权。

05

遥测 JSON 格式

顶层必须包含字符串 ICCID;监测值必须是有限 JSON 数字。

正确示例

{
  "iccid": "8986001234567890123",
  "temperature": 24.6,
  "humidity": 61.2,
  "pressure": 101.3,
  "sequence": 1024
}

无法读取外置流量卡时上传 {"iccid":"0","temperature":24.6}。平台用 iccid 更新设备资料,但不会把它列入监测因子、参数配置或报警展示。

可选设备编号

{
  "iccid": "0",
  "deviceNo": "AGN-00001",
  "metrics": {"temperature": 25.6, "co": 0.439}
}

在 JSON 顶层上传 deviceNo(兼容 device_no),界面自动用它显示设备标识,无需手填。最新有效遥测帧未上传、为空或不合法时,恢复原设备 ID。建议每帧上传字符串以保留前导零;去除首尾空白后限 1–64 个字符、UTF-8 不超过 128 字节,不允许控制/格式字符,也兼容非负整数。两个别名冲突时回退原 ID。

编号不属于监测参数,不能放在 metrics 内,也不能配置单位或报警点。仍需合法的 iccid 和至少一个数字监测值。编号只改显示,不改变账号、设备归属或历史关联。

MQTT 接入标识保持原值

原平台 ID 为 device-001 时,即使显示编号变为 AGN-00001,Client ID 仍是 device-001,发布 Topic 仍是 devices/device-001/telemetry。连接地址、端口及认证以平台签发凭据为准。

兼容的 metrics 对象写法

{"iccid":"0","metrics":{"temperature":24.6,"humidity":61.2}}
number

只有有限 JSON 数字会成为监测因子。

top-level

推荐把温度、湿度、压力等数值直接平铺。

metrics

兼容只包含数字点位的顶层对象。

non-number

字符串、布尔值、null、数组或其他对象不作为监测因子。

错误示例

{
  "iccid": 0,
  "temperature": "24.6",
  "running": true,
  "metrics": [24.5, 24.6]
}

上例的 ICCID 不是字符串,温度不是 JSON 数字,并且保留字段 metrics 不是对象。参数配置中的 key 必须与顶层或 metrics 对象内的数字监测字段名完全一致,且不能使用 iccid、deviceNo、device_no。

06

遥测参数配置

管理员定义字段显示名称、单位、量程和报警阈值。

读取GET /portal-api/v1/devices/{id}/telemetry/parameters
保存PUT /portal-api/v1/devices/{id}/telemetry/parameters
字段用途
key顶层或 metrics 对象中的数字监测字段名;不能使用 iccid、deviceNo、device_no
displayName门户显示名称
unit单位;无单位时使用空字符串
rangeMin / rangeMax量程下限和上限
alarmLow / alarmHigh低报警和高报警阈值
{
  "items": [
    {
      "key": "temperature",
      "displayName": "环境温度",
      "unit": "°C",
      "rangeMin": -40,
      "rangeMax": 85,
      "alarmLow": 0,
      "alarmHigh": 50
    },
    {
      "key": "humidity",
      "displayName": "相对湿度",
      "unit": "%RH",
      "rangeMin": 0,
      "rangeMax": 100,
      "alarmLow": 20,
      "alarmHigh": 85
    }
  ]
}

修改前先读取当前配置,编辑完整 items 后再保存,并以 API 校验响应为准。该接口仅管理员可用,不能把管理员令牌写入设备。

07

调试示例

所有示例均校验服务端证书,且只使用占位凭据。

MQTTX

字段填写内容
Host / Portmqtts://47.94.172.189 / 8883
MQTT Version3.1.1
Client ID<设备ID>,不得追加后缀
Username / Password创建时签发的设备账号和一次性密码
SSL/TLS开启,并选择平台 ca.crt
Client Certificate / Key留空

连接后向 devices/<设备ID>/telemetry 发布以下 Payload,QoS 选 1,Retain 关闭:

{"iccid":"0","temperature":24.6,"humidity":61.2}
Connected 不等于数据已经入站

MQTTX 显示已连接只说明 TLS 和账号认证成功。还必须向正确 Topic 发布符合格式的遥测,门户才会展示数据。

mosquitto_pub · Linux / macOS

DEVICE_ICCID 只用于电脑模拟。真机固件应在运行时从通信模组或厂商 SDK 自动读取,失败时自动使用字符串 "0",不向用户提供手工录入项。

export DEVICE_ID='<设备ID>'
export DEVICE_ICCID='<真实18-22位ICCID;无法读取时填0>'
export MQTT_USERNAME='<设备账号>'
export MQTT_PASSWORD='<设备密码>'

mosquitto_pub \
  -h 47.94.172.189 \
  -p 8883 \
  -V mqttv311 \
  --cafile ./ca.crt \
  -i "$DEVICE_ID" \
  -u "$MQTT_USERNAME" \
  -P "$MQTT_PASSWORD" \
  -t "devices/$DEVICE_ID/telemetry" \
  -m "{\"iccid\":\"$DEVICE_ICCID\",\"temperature\":24.6,\"humidity\":61.2}" \
  -q 1 -d

mosquitto_pub · Windows PowerShell

$deviceId = '<设备ID>'
$deviceIccid = '<真实18-22位ICCID;无法读取时填0>'
$mqttUsername = '<设备账号>'
$mqttPassword = '<设备密码>'
$payload = @{ iccid = $deviceIccid; temperature = 24.6; humidity = 61.2 } | ConvertTo-Json -Compress

mosquitto_pub -h 47.94.172.189 -p 8883 -V mqttv311 `
  --cafile '.\ca.crt' `
  -i $deviceId `
  -u $mqttUsername -P $mqttPassword `
  -t "devices/$deviceId/telemetry" `
  -m $payload `
  -q 1 -d
!

共享计算机上,-P 可能被本机其他进程看到。正式设备应从受保护的密钥存储读取密码,不要把密码写死在脚本中。

Python · paho-mqtt 2.x

先安装 python -m pip install "paho-mqtt>=2,<3",并设置 DEVICE_ID、DEVICE_ICCID、MQTT_USERNAME、MQTT_PASSWORD 环境变量。这是电脑模拟程序;真机移植时将 DEVICE_ICCID 替换为模组自动读取结果。

import json
import os
import ssl
import threading
import time

import paho.mqtt.client as mqtt

device_id = os.environ["DEVICE_ID"]
device_iccid = os.environ.get("DEVICE_ICCID", "0")
topic = f"devices/{device_id}/telemetry"
connected = threading.Event()
connect_error = []


def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code == 0:
        connected.set()
    else:
        connect_error.append(str(reason_code))
        connected.set()


client = mqtt.Client(
    callback_api_version=mqtt.CallbackAPIVersion.VERSION2,
    client_id=device_id,
    protocol=mqtt.MQTTv311,
)
client.on_connect = on_connect
client.username_pw_set(
    os.environ["MQTT_USERNAME"],
    os.environ["MQTT_PASSWORD"],
)
client.tls_set(
    ca_certs="ca.crt",
    cert_reqs=ssl.CERT_REQUIRED,
    tls_version=ssl.PROTOCOL_TLS_CLIENT,
)
client.tls_insecure_set(False)

client.connect("47.94.172.189", 8883, keepalive=60)
client.loop_start()

if not connected.wait(10):
    raise TimeoutError("等待 MQTT CONNACK 超时")
if connect_error:
    raise ConnectionError(f"MQTT 连接失败:{connect_error[0]}")

payload = {
    "iccid": device_iccid,
    "temperature": 24.6,
    "humidity": 61.2,
    "sequence": int(time.time()),
}
message = client.publish(
    topic,
    json.dumps(payload, ensure_ascii=False, separators=(",", ":")),
    qos=1,
    retain=False,
)
message.wait_for_publish(timeout=10)

client.disconnect()
client.loop_stop()
08

上线前检查

真机交付和批量上线前逐项确认。

01

创建设备不提交 ICCID;遥测顶层上传字符串 iccid。

02

每台设备使用独立账号、密码和设备 ID。

03

Client ID 与设备 ID 完全一致,没有后缀或空格。

04

Topic 精确为 devices/<设备ID>/telemetry。

05

至少包含 1 个有限数字监测值;若使用 metrics,它是只含数字点位的对象。

06

已安装正确 CA,TLS 和 hostname 校验均开启。

07

遥测不 Retain,参数 key 与上报字段完全一致。

08

固件、日志、截图和 Git 均不包含设备密码。

  • 检查设备时间同步、断网重连和 1–60 秒指数退避。
  • 检查阿里云安全组允许设备访问 8883/TCP,且未开放公网 1883。
  • 验证错误密码、错误 Topic、重复 Client ID、证书异常和多设备同时上线。
  • 管理员确认参数名称、单位、量程和报警阈值符合现场定义。
09

故障排查

按网络、TLS、认证、身份、Topic、Payload、参数配置的顺序定位。

现象常见原因处理方式
超时或拒绝安全组、出口网络、Broker 状态或端口错误检查 47.94.172.189:8883,不要使用 1883/443
证书校验失败CA 错误、设备时间错误或证书过期使用平台 ca.crt,同步时间,禁止跳过校验
Bad username/password凭据错误、尾部换行或凭据已轮换重新复制凭据,必要时由管理员轮换
连接反复断开真机和调试工具复用同一 Client ID关闭其他客户端,确保单一同名连接
Not authorizedTopic 或设备 ID 不匹配 ACL核对 Client ID 和 devices/<设备ID>/telemetry
已连接但无遥测未发布、Topic 错误、缺少合法 ICCID、没有有效数字点位、metrics 格式错误或发布失败发布顶层含字符串 iccid 且至少含 1 个有限数字监测值的 JSON,并检查客户端结果
名称或单位不正确参数未配置,或 key 与上报字段不同管理员读取并更新遥测参数配置
报警未触发阈值缺失、字段名错误或数值被发成字符串核对 alarmLow/alarmHigh、key 和 JSON 类型
没有真实 ICCID遥测缺少 ICCID、上传数字 0,或值不符合规则内置卡上传 18–22 位数字字符串;无法读取外置卡时上传字符串 "0"

Windows 端口检查

Test-NetConnection 47.94.172.189 -Port 8883

该命令只能验证 TCP 连通性,不能验证 TLS、MQTT 登录、Client ID、Topic ACL 或遥测格式。

容量说明

平台不人为限制同时在线设备数量。实际容量取决于服务器资源、连接数、上报频率、消息大小和数据库负载;正式扩容前应完成持续连接、集体重连、消息峰值、磁盘增长和证书轮换测试。