Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to publish a message to a specific client in Mosquitto MQTT

Tags:

mqtt

Currently we have an app that controls multiple devices through MQTT. Each device subscribes to a unique topic which is named after their device ID. For example, device A has device ID 123 so it will subscribe to topic 123. Then if the app wants to publish control message to device A, then it will publish a topic named 123, which is the device ID of device A.

By doing this, if we have 1000 devices then we will have 1000 topics. This is a really bad design. So we are thinking that maybe we can publish a topic to a specific client by setting the client ID that will receive the topic since each client that connects to the broker will have to set a client ID. However, we did not find any method that allows publishing to a specific client. And it seems that MQTT doesn't handle such thing. It only publishes to clients subscribing to the same topic.

So, is there any other way that we can do to to achieve one topic, but still able to publish message to specific clients?

Thanks!

like image 321
JLT Avatar asked Feb 16 '17 04:02

JLT


2 Answers

There is no way to publish a message to a single subscriber at the MQTT protocol level.

One of the key tenets of a publish/subscribe system is to totally decouple the publisher from the subscribers, there is no way for a publisher to know if there are any subscribers to a given topic let alone target one specifically.

Using a topic for each device is not a problem as there is virtually no overhead in the broker for each topic. You can also use ACLs to ensure that each client can only subscribe their own topic (while still being able to publish to others if needed)

You could use a single topic that all clients subscribe to and encode the target device in the payload and have the device decide if the message is for it's self. One downside to this is that you can't apply ACLs to this model. Another downside is increased network traffic, since uninteresting messages will be sent to many subscribers.

like image 83
hardillb Avatar answered Jan 03 '23 19:01

hardillb


We have managed this within the Mosca MQTT Broker, that is not on protocoll level, but it works fine, by a procedure that the clients send in the course of the subscription a message, containing an options, which controls the forwarding of logging (channel "logger") messages

{"login":{"UserName":"John_Doe","option":["receive_logs"]}}

Retrieve login information and

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;
}

Provide an individual "authorizeForward", checking if the user is supposed to receive the relevent contents

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);
};

The next step will be to request the data from a server and read the rights from there...

like image 38
hsc Avatar answered Jan 03 '23 18:01

hsc