亚马逊AWS官方博客

Amazon IoT Core Direct Messaging 在楼宇控制场景实战

摘要:在传统的 MQTT publish/subscribe 模型下,要向某一台设备下发指令,你得先把消息发布到设备订阅的主题上。这带来两个现实痛点:一是设备必须提前订阅对应主题,主题设计与权限管理变得繁琐;二是发完就“知足”,没有内置机制告诉你设备到底收到没有。2026 年,Amazon IoT Core 推出了 Direct Messaging(直接消息发送)。你只需调用 SendDirectMessage API,指定接收方的 MQTT client ID 和目标主题,就能把消息“点对点”直送给该设备——设备无需预先订阅。当 confirmation=true 时,服务会以 QoS 1 下发并等待设备回 PUBACK,从而拿到端到端的送达确认。


一、引言:从“广播喊话”到“精准点名”

在传统的 MQTT publish/subscribe 模型下,要向某一台设备下发指令,你得先把消息发布到设备订阅的主题上。这带来两个现实痛点:一是设备必须提前订阅对应主题,主题设计与权限管理变得繁琐;二是发完就“知足”,没有内置机制告诉你设备到底收到没有。

2026 年,Amazon IoT Core 推出了 Direct Messaging(直接消息发送)。你只需调用 SendDirectMessage API,指定接收方的 MQTT client ID 和目标主题,就能把消息“点对点”直送给该设备——设备无需预先订阅。当 confirmation=true 时,服务会以 QoS 1 下发并等待设备回 PUBACK,从而拿到端到端的送达确认。

二、场景案例:楼宇设备的远程调控

设想一个智能楼宇运营平台(BMS),接入了数千台暖通控制器、照明网关、电梯与门禁控制器。运营人员常需要向某一台特定设备下发指令,例如:

  • 晚间把某栋楼的暖通控制器 HVAC-01 切到节能模式;
  • 给某个区域的照明网关 LIGHT-07 下发调光/关灯指令;
  • 向某台控制器下发参数重置或固件校验命令,并确认设备确实收到。

这类需求的共同点是:需要“点名”到单台设备,且对送达结果敏感。如果一条关闭暖通的指令没有送达,可能导致能耗浪费或现场投诉。Direct Messaging 恰好命中这一场景:按 client ID 定向、免订阅、带送达回执。

三、什么是 Direct Messaging

SendDirectMessage 是一个 HTTP API,向一个由 MQTT client ID 标识的单一设备发送消息,接收方无需订阅目标主题。其核心特性:

  • 按 client ID 定向:直接指向单个设备,不需要主题路由。
  • 送达确认:confirmation=true 时以 QoS 1 下发并等待 PUBACK,拿到端到端回执;confirmation=false 时以 QoS 0 下发,不等确认。
  • 可观测性:API 返回详细 HTTP 状态码,并可通过 CloudWatch Logs 查看送达状态与失败 reason。

需注意的三点限制:直接消息不会被 IoT Rules 引擎处理、不会为离线设备排队、也不支持 retained 消息。

四、解决方案架构

4.1 架构图

图 1:楼宇设备远程调控的 Direct Messaging 端到端架构

[图 1:楼宇设备远程调控的 Direct Messaging 端到端架构]

4.2 组件与数据流说明

  • 楼宇运营平台:运营人员在 BMS 控制台发起指令,后端调度服务调用 SendDirectMessage API(HTTPS POST)。
  • Amazon IoT Core:根据 client_id 定向,经 IAM/设备策略鉴权后,通过 MQTT Broker 以指定 QoS 下发到目标设备。
  • 楼宇现场设备:目标设备作为 MQTT Client 接收消息(即使未订阅该主题),处理后回 PUBACK。
  • 可观测性回路:API 同步返回 HTTP 状态码,CloudWatch Logs 记录每次送达的详情,便于定位离线或失败设备。

五、动手实践

5.1 前置条件

  • 确保你的 Amazon CLI 或者 boto3 使用的最新版本(版本 ≥ boto3 1.43 / aws-cli 2.37)。
  • 标设备已以唯一 client ID 连接到 Amazon IoT Core(否则返回 404)。
  • 发送端已获取 IoT data endpoint(设备数据端点)。

5.2 配置 IAM / 设备策略

发送端策略需授予 iot:SendDirectMessage(目标 client ID 作为资源,可选用 iot:Topic 条件限制主题):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "iot:SendDirectMessage",
    "Resource": "arn:aws-cn:iot:cn- northwest-1:ACCOUNT:client/HVAC-01",
    "Condition": {
      "ForAllValues:StringEquals": {
        "iot:Topic": ["commands/hvac/set-mode"]
      }
    }
  }]
}

接收端(设备)策略需授予 iot:Receive 权限。注意:接收直接消息无需 iot:Subscribe 权限。

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "iot:Receive",
    "Resource": "arn:aws-cn:iot:cn- northwest-1:ACCOUNT:topic/commands/hvac/set-mode"
  }]
}

5.3 资源准备

# 1) 证书 + 私钥
aws iot create-keys-and-certificate --set-as-active \
  --certificate-pem-outfile device.pem.crt \
  --public-key-outfile public.pem.key \
  --private-key-outfile private.pem.key \
  --query 'certificateArn' --output text --profile cn --region cn-northwest-1
# 记录下CERT_ARN,设置为变量
CERT_ARN=$(aws iot list-certificates \
  --profile cn --region cn-northwest-1 \
  --query 'certificates[0].certificateArn' --output text)
# 同时也把Amazon Root CA下载下来
curl -o Amazon-root-CA-1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem

# 2) Thing
aws iot create-thing --thing-name HVAC-01 --profile cn --region cn-northwest-1

# 3) 设备策略:Connect + Receive,故意不给 iot:Subscribe(验证免订阅收消息)
aws iot create-policy --policy-name hvac01-device-policy \
  --policy-document file://device-policy.json --profile cn --region cn-northwest-1

# 4) attach
aws iot attach-policy --policy-name hvac01-device-policy --target "$CERT_ARN" --profile cn --region cn-northwest-1
aws iot attach-thing-principal --thing-name HVAC-01 --principal "$CERT_ARN" --profile cn --region cn-northwest-1

设备/发送端策略

   {
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "iot:Connect",           "Resource": "arn:aws-cn:iot:cn-northwest-1:ACCOUNT:client/HVAC-01" },
    { "Effect": "Allow", "Action": "iot:Receive",           "Resource": "arn:aws-cn:iot:cn-northwest-1:ACCOUNT:topic/commands/hvac/set-mode" },
    { "Effect": "Allow", "Action": "iot:SendDirectMessage", "Resource": "arn:aws-cn:iot:cn-northwest-1:ACCOUNT:client/*" }
  ]
}

5.4 设备端:免订阅接受

用 Amazon IoT Device SDK v2 (Python),MQTT 连接后不调用 subscribe,用 on_message 捕获所有到达的 publish

# 建议用虚拟环境(可选但推荐)
python3 -m venv venv
source venv/bin/activate
# 安装 Amazon IoT Device SDK v2
pip install awsiotsdk
# 测试代码
cat > device_receiver.py <<'EOF'
from awsiot import mqtt_connection_builder
#替换成自己真实的端点
ENDPOINT = "xxxxxxxxxxx-ats.iot.cn-northwest-1.amazonaws.com.cn"
def on_msg(topic, payload, dup, qos, retain, **kw):
print(f"[DEVICE-RX] topic={topic} qos={qos} payload={payload.decode()}")
conn = mqtt_connection_builder.mtls_from_path(
endpoint=ENDPOINT,
cert_filepath="device.pem.crt",
pri_key_filepath="private.pem.key",
ca_filepath="Amazon-root-CA-1.pem",
client_id="HVAC-01",
clean_session=True,
)
conn.on_message(on_msg) # 关键:整连接级回调,不依赖 subscribe
conn.connect().result()
print("[DEVICE] CONNECTED (no subscribe issued)")
# 保持进程不退出,持续接收消息
import time
while True:
time.sleep(1)
EOF

最后运行 python 代码,会看到如下图:

[图 2]

5.5 发送端代码-CLI

aws iot-data send-direct-message \
    --client-id HVAC-01 \
    --topic commands/hvac/set-mode \
    --confirmation \
    --timeout 10 \
    --payload '{"mode":"eco","zone":"B3"}' \
    --cli-binary-format raw-in-base64-out \
    --region cn- northwest-1 \
    --endpoint-url https://IoT_data_endpoint 

[图 3]

5.6 查看设备端接受

要充分发挥 Direct Messaging 的价值,设备端 MQTT Client 需满足两点:

  • 处理未订阅主题的消息——部分 MQTT 实现会丢弃未订阅主题的消息,需确保消息回调不依赖订阅状态。
  • 正确处理由 API 决定的 QoS——confirmation=true 时消息以 QoS 1 到达,客户端必须回 PUBACK。

[图 4]

我们可以看到模拟设备正常的接收到了下发的指令。

六、送达状态与错误处理

SendDirectMessage API 返回的常见 HTTP 状态码与推荐处理如下:

HTTP 码 含义与推荐处理
200 已送达(confirmation=true 时表示接收方已确认)。
400 参数无效。检查主题名与 client-id 是否合法并已 URL 编码。
403 权限不足。发送端缺 iot:SendDirectMessage 或接收端缺 iot:Receive,修正对应策略。
404 目标 client ID 未连接。验证设备在线后重试(可能处于持久会话但当前离线)。
413 Payload 过大。减小消息体后重试。
429 超频。降低请求速率并实施指数退避。
500 服务端错误。指数退避重试;持续存在则携 traceId 联系支持。
504 超时未收到 PUBACK。增大 timeout、确认设备对 QoS 1 回 PUBACK,或检查设备处理是否过慢。

七、最佳实践与限制

  • 合理设置 timeout:HTTP 客户端超时应大于 API 的 timeout 参数,避免客户端先于服务端断开。
  • 对 429/500/504 实施指数退避重试,避免雪崩。
  • 与 Rules 的取舍:直接消息不经 IoT Rules,若需规则路由/落库等加工,仍应走传统 publish 模式。
  • 控制 payload 大小并对主题/client-id 做 URL 编码(含空格、斜杠、UTF-8 字符时)。
  • 开启 CloudWatch 日志,利用 reason 字段做程序化错误处理与告警。

八、Direct Messaging 与 MQTT Broker 对比

对比维度 Direct Messaging(直接消息) Broker Pub/Sub(发布/订阅)
通信模式 点对点(一对一) 发布/订阅,扇出(一对多)
路由方式 按 MQTT Client ID 定向 通过 MQTT 主题(Topic)匹配订阅
接口/协议 SendDirectMessage HTTP API MQTT 长连接
接收方是否需订阅 无需订阅(仅需 iot:Receive) 必须预先订阅(需 iot:Subscribe)
送达确认 端到端确认(QoS 1 等待设备 PUBACK) 仅 Broker 层确认,不代表设备收到
离线设备反馈 即时:设备未连接立即返回 404 无:publish 照常成功,无从得知
适用场景 单台设备精准下发指令并确认送达 一对多广播/扇出、离线消息排队、Rules 加工

九、总结与参考

Direct Messaging 为“向单台设备精准下发指令并确认送达”这类场景提供了简洁、可观测的点对点通信能力。在楼宇设备远程调控、设备运维、应急控制等对送达确认敏感的场景中,它能显著降低主题设计与权限管理的复杂度,并提升运维可见性。建议从非关键指令入手试点,逐步推广到关键控制链路。

➡️ 下一步行动:

相关产品:

相关文章:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

路万华

解决方案架构师,15+的技术研发和架构经验,在电力、新能源和楼宇自控行业的物联网领域有丰富的经验。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用