[英]how to subscribe to specific topic inside rout in nodejs
我有这个用于物联网设备的过程。
从移动应用程序接收 HTTP 请求到我的服务器的消息 - 应用程序的用户通过 api 向服务器发送消息以在 iot 设备中打开中继应用程序发送 iot 设备的设备 ID。
服务器通过 MQTT 将上述步骤中的消息发布到特定主题并等待 5 秒以通过 MQTT 从设备接收到特定主题的动作响应。 如果在 5 秒内收到响应,则服务器向应用程序发送成功响应,然后用户知道操作是否成功,否则发送错误响应到步骤 1 中的原始 HTTP 请求
我没有找到 sulustion 如何做到这一点以及如何订阅特定主题设备将在 nodejs 中的路由内回复
我使用aws-iot核心的mqtt
var awsIot = require("aws-iot-device-sdk");
var http = require("http");
const port = "8082";
var url = require("url");
const express = require("express");
const { json } = require("body-parser");
const app = express();
var cors = require("cors");
const { Console } = require("console");
//const { rejects } = require("assert");
//const { resolve } = require("path/posix");
app.use(cors());
var device = awsIot.device({
keyPath:
"AWS/d337405f03a230065b9ngngefafa6b908ca03bed63e34f0d01fbf651ca8c58b75-private.pem.key",
certPath:
"AWS/d337405f03a230065b97f9efhhhgsfafa6b908ca03bed63e34f0d01fbf651ca8c58b75-certificate.pem.crt",
caPath: "AWS/roorCA.pem",
clientId: "testawsconection1", //esp32-erocam-122021
host: "a2nl9gsbgfihjibb-ats.iot.eu-west-1.amazonaws.com",
});
async function getReq(topicLisiner) {
const timeOutPromise = new Promise((reslove, rejects) =>
setTimeout(() => {
rejects("error time out");
}, 10000)
);
const promisDevice = new Promise((reslove, rejects) => {
///
device.on("connect", function () {
device.subscribe("esp32/pub");
});
///
device.on(
"message",
function (topic, payload) {
//device.subscribe(topicLisiner);
console.log("topic1", topic, payload.toString());
if (topic) {
if (topic == topicLisiner) {
device.unsubscribe(topicLisiner);
device.on("close", function () {
device.unsubscribe(topicLisiner);
});
reslove(payload.toString());
}
} else {
rejects("error1");
}
},
(error, result) => {
if (error) rejects(error);
else {
reslove(result);
}
}
);
});
return Promise.race([promisDevice, timeOutPromise]);
}
app.get("/test", async (req, res) => {
device.publish("esp32/eran", JSON.stringify({ "open door": "5" }));
console.log("----------------");
try {
const result = await getReq("esp32/pub");
console.log(result);
return res.send(result);
} catch (error) {}
return res.send("error time out-");
});
///
简短的回答是您不这样做,除非您非常确定自己在做什么,否则将诸如 HTTP 之类的同步请求/响应协议与异步发布/订阅协议混合通常是一个坏主意。 将 MQTT 发布移动到移动应用程序比尝试在中间添加HTTP会好得多。
更长的答案,这是可能的,但它不能扩展。 您只能拥有一个 HTTP 服务器来完成这项工作,因为它需要跟踪所有正在进行的请求。 它还要求发布的消息包含一个唯一的 ID,并将请求发布到设备,并且设备需要使用此 ID 进行响应。
您订阅了一个匹配所有设备的主题并一次处理它们。 以下是基于 mqtt.js 客户端库的示例,但应该是使用 AWS 库的方法的指南。
var waitingRequests = {}
device.on('message', function(topic, message){
var msg = JSON.parse(message)
var waiting = waitingRequests[msg.id]
if (waiting) ({
waiting.res.send(msg)
delete waitingRequests[msg.id]
}
})
//checks every second for timed out requests
setInterval(function(){
var now = Date.now()
var keys = Object.keys(waitingRequests)
for (var key in keys) {
var waiting = waitingRequests[keys[key]]
var diff = now - waiting.timestamp;
if (diff > 5000) {
//timed out
waiting.res.send("error timed out")
delete waitingRequests[keys[key]]
}
}
}, 1000)
app.get("/test", async (req, res) => {
device.publish("esp32/eran", JSON.stringify({ "open door": "5", "id": "someId" }));
waitingRequests["someId"] = { res: res, timestamp: Date.now()}
});
在我的真实应用中将有无限的用户和无限的设备
从您的回答中,我不明白nodejs服务器如何同时控制来自diffrunt用户的许多相同的http req并发布和订阅diffrunt设备,因为当他重新运行消息时,ech设备适用于其他http req
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.