目前我们有一个通过MQTT控制多个设备的应用程序。每个设备都订阅一个以其设备ID命名的唯一主题。例如,设备A具有设备ID 123,因此它将订阅主题123.然后,如果应用想要将控制消息发布到设备A,则它将发布名为123的主题,这是设备A的设备ID。
通过这样做,如果我们有1000个设备,那么我们将有1000个主题。这是一个非常糟糕的设计。因此,我们可能会考虑通过设置将接收主题的客户端ID将主题发布到特定客户端,因为连接到代理的每个客户端都必须设置客户端ID。但是,我们没有找到任何允许发布到特定客户端的方法。似乎MQTT并没有处理这样的事情。它只发布给订阅同一主题的客户。
那么,有没有其他方法可以实现一个主题,但仍然能够向特定客户发布消息?
谢谢!
答案 0 :(得分:11)
无法在MQTT协议级别向单个订户发布消息。
发布/订阅系统的一个主要租户是将发布者与订阅者完全分离,发布者无法知道某个主题是否有任何订阅者,更不用说专门定位一个主题。
为每个设备使用主题不是问题,因为它们在每个主题的代理中几乎没有开销。您还可以使用ACL来确保每个客户端只能订阅自己的主题(如果需要,仍然可以发布给其他人)
您可以使用所有客户端订阅的单个主题,并在有效负载中对目标设备进行编码,并让设备决定该消息是否适合自己。不利的一面是您无法将ACL应用于此模型。
答案 1 :(得分:0)
我们已经在Mosca MQTT Broker中对此进行了管理,该协议不在协议级别上,但是可以通过客户端在订阅过程中发送包含选项(用于控制转发)的消息的过程来正常运行记录(通道“记录器”)消息
{"login":{"UserName":"John_Doe","option":["receive_logs"]}}
获取登录信息和
let LoggedInUsers = {};
server.on('published', function(packet, client) {
let contentstr = packet.payload.toString();
//parse Package Content
let packagecontent = JSON.parse(contentstr);
if (packagecontent.hasOwnProperty('login'))
if (!LoggedInUsers.hasOwnProperty(client.id))
LoggedInUsers[client.id] = packagecontent.login;
}
提供一个单独的“ authorizeForward”,检查用户是否应该接收相关事件内容
let authorizeForward = function(client, packet, callback) {
if (packet.topic === "logger" && LoggedInUsers.hasOwnProperty(client.id))
if (LoggedInUsers[client.id].option.indexOf('receive_logs') === -1)
return;
callback(null, true);
};
下一步是从服务器请求数据并从那里读取权限...