能否在AWS IoT发布函数回调中获取订阅设备的返回结果?
AWS Lambda IoT发布消息请求设备信息时,publish回调result为undefined的问题解决
问题背景
我用AWS Lambda编写了函数,通过AWS IoT向远程设备发布消息,设备仅订阅包含自身ID的主题。发布指令类消息正常,但请求设备信息时,发现publish的回调虽能触发,但result始终为undefined,无法找到让设备端填充该值的方式。
Lambda端发布代码
iot.device.publish(`pi/${device}/${event.body.actionType}`, payload,null,(err,result) => { util.log(`In publish callback. err: ${err} result: ${result}`) if (device === event.body.devices[event.body.devices.length - 1]) { published = true } if(err) { util.log('Failure:',err.message) } })
设备端消息处理代码
device.on('message', (topic, data) => { let payload = parsePayload(data) logger.info(`received iot message for topic ${topic} with payload ${payload}`) })
尝试扩展设备端参数列表后,仍无法获取有效回调:
device.on('message', (topic, data, nullObject, callback) => { let payload = parsePayload(data) logger.info(`received iot message for topic ${topic} with payload ${payload} nullObject ${typeof nullObject} callback ${typeof callback}`) })
核心原因
AWS IoT的publish方法回调不支持从设备端返回数据:
- 该回调仅用于确认消息是否成功被AWS IoT服务接收(并非确认设备端已消费)
- 回调的
result参数本身设计为undefined,设备端没有任何途径访问或调用这个回调——MQTT是单向发布订阅模型,原生不提供请求响应的双向绑定能力
可行解决方案(结合实践更新)
要实现「请求设备信息并获取返回值」的需求,必须采用双向主题通信的模式,具体实现思路:
- 封装publish为带超时的Promise:将每个发布请求包装成Promise,存入以唯一
requestId为key的请求队列,同时设置超时时间,超时则拒绝Promise并返回“未收到响应” - 指定专属响应主题:Lambda发布请求时,在payload中加入唯一
requestId,要求设备端收到请求后,将设备信息发布到pi/${device}/response/${requestId}这类专属响应主题 - Lambda订阅响应主题处理返回:Lambda提前订阅所有设备的响应主题,收到响应消息时解析出
requestId,从队列中找到对应Promise,用设备返回的信息resolve该Promise;超时则自动触发reject
目前已参考同事代码完成实现:将publish包装为Promise存入队列,当收到设备响应时,取出对应队列项取消超时,用设备返回详情resolve Promise。
内容的提问来源于stack exchange,提问作者Ed Trembicki-Guy
相关产品推荐
相关产品推荐

